summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStan Lo <stan.lo@shopify.com>2025-07-07 21:37:02 +0100
committerMax Bernstein <tekknolagi@gmail.com>2025-07-08 12:28:03 -0400
commitaf892c1be359900ef5f6be0724cbbec69f3650f0 (patch)
tree1aff20d602bf57c5b77aac4a528cc0edfee63015
parent6c20082852a2f69a11d950b98ff179b2b737ed67 (diff)
ZJIT: More accurately model Class types
-rw-r--r--zjit/src/hir.rs22
-rw-r--r--zjit/src/hir_type/gen_hir_type.rb4
-rw-r--r--zjit/src/hir_type/hir_type.inc.rs78
-rw-r--r--zjit/src/hir_type/mod.rs4
4 files changed, 51 insertions, 57 deletions
diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs
index 20ffe17683..3af2a6abf7 100644
--- a/zjit/src/hir.rs
+++ b/zjit/src/hir.rs
@@ -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
diff --git a/zjit/src/hir_type/gen_hir_type.rb b/zjit/src/hir_type/gen_hir_type.rb
index bbd0e1ed32..660ac342cf 100644
--- a/zjit/src/hir_type/gen_hir_type.rb
+++ b/zjit/src/hir_type/gen_hir_type.rb
@@ -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.
diff --git a/zjit/src/hir_type/hir_type.inc.rs b/zjit/src/hir_type/hir_type.inc.rs
index 2c6fb48ea5..21ef8c8bdd 100644
--- a/zjit/src/hir_type/hir_type.inc.rs
+++ b/zjit/src/hir_type/hir_type.inc.rs
@@ -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);
diff --git a/zjit/src/hir_type/mod.rs b/zjit/src/hir_type/mod.rs
index 907582c251..f0e701612d 100644
--- a/zjit/src/hir_type/mod.rs
+++ b/zjit/src/hir_type/mod.rs
@@ -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 }); }