ZJIT: More accurately model Class types

This commit is contained in:
Stan Lo 2025-07-07 21:37:02 +01:00 committed by Max Bernstein
parent 6c20082852
commit af892c1be3
4 changed files with 51 additions and 57 deletions

View file

@ -4196,10 +4196,10 @@ mod tests {
assert_method_hir("test", expect![[r#"
fn test:
bb0(v0:BasicObject, v1:BasicObject):
v3:ClassExact[VMFrozenCore] = Const Value(VALUE(0x1000))
v3:Class[VMFrozenCore] = Const Value(VALUE(0x1000))
v5:HashExact = NewHash
v7:BasicObject = SendWithoutBlock v3, :core#hash_merge_kwd, v5, v1
v8:ClassExact[VMFrozenCore] = Const Value(VALUE(0x1000))
v8:Class[VMFrozenCore] = Const Value(VALUE(0x1000))
v9:StaticSymbol[:b] = Const Value(VALUE(0x1008))
v10:Fixnum[1] = Const Value(1)
v12:BasicObject = SendWithoutBlock v8, :core#hash_merge_ptr, v7, v9, v10
@ -4648,7 +4648,7 @@ mod tests {
assert_method_hir_with_opcode("test", YARVINSN_putspecialobject, expect![[r#"
fn test:
bb0(v0:BasicObject):
v2:ClassExact[VMFrozenCore] = Const Value(VALUE(0x1000))
v2:Class[VMFrozenCore] = Const Value(VALUE(0x1000))
v3:BasicObject = PutSpecialObject CBase
v4:StaticSymbol[:aliased] = Const Value(VALUE(0x1008))
v5:StaticSymbol[:__callee__] = Const Value(VALUE(0x1010))
@ -5889,7 +5889,7 @@ mod opt_tests {
bb0(v0:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, C)
v7:ClassExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
v7:Class[VALUE(0x1008)] = Const Value(VALUE(0x1008))
Return v7
"#]]);
}
@ -5905,16 +5905,16 @@ mod opt_tests {
bb0(v0:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, String)
v15:ClassExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
v15:Class[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1010, Class)
v18:ClassExact[VALUE(0x1018)] = Const Value(VALUE(0x1018))
v18:Class[VALUE(0x1018)] = Const Value(VALUE(0x1018))
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1020, Module)
v21:ClassExact[VALUE(0x1028)] = Const Value(VALUE(0x1028))
v21:Class[VALUE(0x1028)] = Const Value(VALUE(0x1028))
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1030, BasicObject)
v24:ClassExact[VALUE(0x1038)] = Const Value(VALUE(0x1038))
v24:Class[VALUE(0x1038)] = Const Value(VALUE(0x1038))
v11:ArrayExact = NewArray v15, v18, v21, v24
Return v11
"#]]);
@ -6107,7 +6107,7 @@ mod opt_tests {
bb0(v0:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, Foo::Bar::C)
v7:ClassExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
v7:Class[VALUE(0x1008)] = Const Value(VALUE(0x1008))
Return v7
"#]]);
}
@ -6124,7 +6124,7 @@ mod opt_tests {
bb0(v0:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, C)
v20:ClassExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
v20:Class[VALUE(0x1008)] = Const Value(VALUE(0x1008))
v4:NilClassExact = Const Value(nil)
v11:BasicObject = SendWithoutBlock v20, :new
Return v11
@ -6147,7 +6147,7 @@ mod opt_tests {
bb0(v0:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, C)
v22:ClassExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
v22:Class[VALUE(0x1008)] = Const Value(VALUE(0x1008))
v4:NilClassExact = Const Value(nil)
v5:Fixnum[1] = Const Value(1)
v13:BasicObject = SendWithoutBlock v22, :new, v5

View file

@ -74,8 +74,8 @@ base_type "Hash"
base_type "Range"
base_type "Set"
base_type "Regexp"
base_type "Class"
base_type "Module"
module_class, _ = base_type "Module"
module_class.subtype "Class"
(integer, integer_exact) = base_type "Integer"
# CRuby partitions Integer into immediate and non-immediate variants.

View file

@ -9,7 +9,7 @@ mod bits {
pub const BasicObjectSubclass: u64 = 1u64 << 3;
pub const Bignum: u64 = 1u64 << 4;
pub const BoolExact: u64 = FalseClassExact | TrueClassExact;
pub const BuiltinExact: u64 = ArrayExact | BasicObjectExact | ClassExact | FalseClassExact | FloatExact | HashExact | IntegerExact | ModuleExact | NilClassExact | ObjectExact | RangeExact | RegexpExact | SetExact | StringExact | SymbolExact | TrueClassExact;
pub const BuiltinExact: u64 = ArrayExact | BasicObjectExact | FalseClassExact | FloatExact | HashExact | IntegerExact | ModuleExact | NilClassExact | ObjectExact | RangeExact | RegexpExact | SetExact | StringExact | SymbolExact | TrueClassExact;
pub const CBool: u64 = 1u64 << 5;
pub const CDouble: u64 = 1u64 << 6;
pub const CInt: u64 = CSigned | CUnsigned;
@ -27,59 +27,57 @@ mod bits {
pub const CUnsigned: u64 = CUInt16 | CUInt32 | CUInt64 | CUInt8;
pub const CValue: u64 = CBool | CDouble | CInt | CNull | CPtr;
pub const CallableMethodEntry: u64 = 1u64 << 17;
pub const Class: u64 = ClassExact | ClassSubclass;
pub const ClassExact: u64 = 1u64 << 18;
pub const ClassSubclass: u64 = 1u64 << 19;
pub const DynamicSymbol: u64 = 1u64 << 20;
pub const Class: u64 = 1u64 << 18;
pub const DynamicSymbol: u64 = 1u64 << 19;
pub const Empty: u64 = 0u64;
pub const FalseClass: u64 = FalseClassExact | FalseClassSubclass;
pub const FalseClassExact: u64 = 1u64 << 21;
pub const FalseClassSubclass: u64 = 1u64 << 22;
pub const Fixnum: u64 = 1u64 << 23;
pub const FalseClassExact: u64 = 1u64 << 20;
pub const FalseClassSubclass: u64 = 1u64 << 21;
pub const Fixnum: u64 = 1u64 << 22;
pub const Float: u64 = FloatExact | FloatSubclass;
pub const FloatExact: u64 = Flonum | HeapFloat;
pub const FloatSubclass: u64 = 1u64 << 24;
pub const Flonum: u64 = 1u64 << 25;
pub const FloatSubclass: u64 = 1u64 << 23;
pub const Flonum: u64 = 1u64 << 24;
pub const Hash: u64 = HashExact | HashSubclass;
pub const HashExact: u64 = 1u64 << 26;
pub const HashSubclass: u64 = 1u64 << 27;
pub const HeapFloat: u64 = 1u64 << 28;
pub const HashExact: u64 = 1u64 << 25;
pub const HashSubclass: u64 = 1u64 << 26;
pub const HeapFloat: u64 = 1u64 << 27;
pub const Immediate: u64 = FalseClassExact | Fixnum | Flonum | NilClassExact | StaticSymbol | TrueClassExact | Undef;
pub const Integer: u64 = IntegerExact | IntegerSubclass;
pub const IntegerExact: u64 = Bignum | Fixnum;
pub const IntegerSubclass: u64 = 1u64 << 29;
pub const Module: u64 = ModuleExact | ModuleSubclass;
pub const ModuleExact: u64 = 1u64 << 30;
pub const ModuleSubclass: u64 = 1u64 << 31;
pub const IntegerSubclass: u64 = 1u64 << 28;
pub const Module: u64 = Class | ModuleExact | ModuleSubclass;
pub const ModuleExact: u64 = 1u64 << 29;
pub const ModuleSubclass: u64 = 1u64 << 30;
pub const NilClass: u64 = NilClassExact | NilClassSubclass;
pub const NilClassExact: u64 = 1u64 << 32;
pub const NilClassSubclass: u64 = 1u64 << 33;
pub const Object: u64 = Array | Class | FalseClass | Float | Hash | Integer | Module | NilClass | ObjectExact | ObjectSubclass | Range | Regexp | Set | String | Symbol | TrueClass;
pub const ObjectExact: u64 = 1u64 << 34;
pub const ObjectSubclass: u64 = 1u64 << 35;
pub const NilClassExact: u64 = 1u64 << 31;
pub const NilClassSubclass: u64 = 1u64 << 32;
pub const Object: u64 = Array | FalseClass | Float | Hash | Integer | Module | NilClass | ObjectExact | ObjectSubclass | Range | Regexp | Set | String | Symbol | TrueClass;
pub const ObjectExact: u64 = 1u64 << 33;
pub const ObjectSubclass: u64 = 1u64 << 34;
pub const Range: u64 = RangeExact | RangeSubclass;
pub const RangeExact: u64 = 1u64 << 36;
pub const RangeSubclass: u64 = 1u64 << 37;
pub const RangeExact: u64 = 1u64 << 35;
pub const RangeSubclass: u64 = 1u64 << 36;
pub const Regexp: u64 = RegexpExact | RegexpSubclass;
pub const RegexpExact: u64 = 1u64 << 38;
pub const RegexpSubclass: u64 = 1u64 << 39;
pub const RegexpExact: u64 = 1u64 << 37;
pub const RegexpSubclass: u64 = 1u64 << 38;
pub const RubyValue: u64 = BasicObject | CallableMethodEntry | Undef;
pub const Set: u64 = SetExact | SetSubclass;
pub const SetExact: u64 = 1u64 << 40;
pub const SetSubclass: u64 = 1u64 << 41;
pub const StaticSymbol: u64 = 1u64 << 42;
pub const SetExact: u64 = 1u64 << 39;
pub const SetSubclass: u64 = 1u64 << 40;
pub const StaticSymbol: u64 = 1u64 << 41;
pub const String: u64 = StringExact | StringSubclass;
pub const StringExact: u64 = 1u64 << 43;
pub const StringSubclass: u64 = 1u64 << 44;
pub const Subclass: u64 = ArraySubclass | BasicObjectSubclass | ClassSubclass | FalseClassSubclass | FloatSubclass | HashSubclass | IntegerSubclass | ModuleSubclass | NilClassSubclass | ObjectSubclass | RangeSubclass | RegexpSubclass | SetSubclass | StringSubclass | SymbolSubclass | TrueClassSubclass;
pub const StringExact: u64 = 1u64 << 42;
pub const StringSubclass: u64 = 1u64 << 43;
pub const Subclass: u64 = ArraySubclass | BasicObjectSubclass | FalseClassSubclass | FloatSubclass | HashSubclass | IntegerSubclass | ModuleSubclass | NilClassSubclass | ObjectSubclass | RangeSubclass | RegexpSubclass | SetSubclass | StringSubclass | SymbolSubclass | TrueClassSubclass;
pub const Symbol: u64 = SymbolExact | SymbolSubclass;
pub const SymbolExact: u64 = DynamicSymbol | StaticSymbol;
pub const SymbolSubclass: u64 = 1u64 << 45;
pub const SymbolSubclass: u64 = 1u64 << 44;
pub const TrueClass: u64 = TrueClassExact | TrueClassSubclass;
pub const TrueClassExact: u64 = 1u64 << 46;
pub const TrueClassSubclass: u64 = 1u64 << 47;
pub const Undef: u64 = 1u64 << 48;
pub const AllBitPatterns: [(&'static str, u64); 79] = [
pub const TrueClassExact: u64 = 1u64 << 45;
pub const TrueClassSubclass: u64 = 1u64 << 46;
pub const Undef: u64 = 1u64 << 47;
pub const AllBitPatterns: [(&'static str, u64); 77] = [
("Any", Any),
("RubyValue", RubyValue),
("Immediate", Immediate),
@ -133,8 +131,6 @@ mod bits {
("FalseClassExact", FalseClassExact),
("DynamicSymbol", DynamicSymbol),
("Class", Class),
("ClassSubclass", ClassSubclass),
("ClassExact", ClassExact),
("CallableMethodEntry", CallableMethodEntry),
("CValue", CValue),
("CInt", CInt),
@ -160,7 +156,7 @@ mod bits {
("ArrayExact", ArrayExact),
("Empty", Empty),
];
pub const NumTypeBits: u64 = 49;
pub const NumTypeBits: u64 = 48;
}
pub mod types {
use super::*;
@ -192,8 +188,6 @@ pub mod types {
pub const CValue: Type = Type::from_bits(bits::CValue);
pub const CallableMethodEntry: Type = Type::from_bits(bits::CallableMethodEntry);
pub const Class: Type = Type::from_bits(bits::Class);
pub const ClassExact: Type = Type::from_bits(bits::ClassExact);
pub const ClassSubclass: Type = Type::from_bits(bits::ClassSubclass);
pub const DynamicSymbol: Type = Type::from_bits(bits::DynamicSymbol);
pub const Empty: Type = Type::from_bits(bits::Empty);
pub const FalseClass: Type = Type::from_bits(bits::FalseClass);

View file

@ -214,7 +214,7 @@ impl Type {
Type { bits: bits::ModuleExact, spec: Specialization::Object(val) }
}
else if val.builtin_type() == RUBY_T_CLASS {
Type { bits: bits::ClassExact, spec: Specialization::Object(val) }
Type { bits: bits::Class, spec: Specialization::Object(val) }
}
else if val.class_of() == unsafe { rb_cRegexp } {
Type { bits: bits::RegexpExact, spec: Specialization::Object(val) }
@ -417,7 +417,7 @@ impl Type {
return Some(val);
}
if self.is_subtype(types::ArrayExact) { return Some(unsafe { rb_cArray }); }
if self.is_subtype(types::ClassExact) { return Some(unsafe { rb_cClass }); }
if self.is_subtype(types::Class) { return Some(unsafe { rb_cClass }); }
if self.is_subtype(types::FalseClassExact) { return Some(unsafe { rb_cFalseClass }); }
if self.is_subtype(types::FloatExact) { return Some(unsafe { rb_cFloat }); }
if self.is_subtype(types::HashExact) { return Some(unsafe { rb_cHash }); }