diff options
| author | Alan Wu <XrXr@users.noreply.github.com> | 2026-04-09 18:40:17 -0400 |
|---|---|---|
| committer | Alan Wu <XrXr@users.noreply.github.com> | 2026-04-09 19:26:19 -0400 |
| commit | 0c1ce03b8c8431d27bc45f88541929881edd4e3e (patch) | |
| tree | 21e222b2a51ce215642547bf18ad6a6a14565839 | |
| parent | 8aa2322bb77120ab39ee63dd27b2d17c60f919ff (diff) | |
ZJIT: Make `hir::types::Class` not final and have it include metaclasses
Every class boots with a metaclass, and all metaclasses are subclasses
of Class, so `types::Class` has no business in `ExactBitsAndClass`.
In fact, we should never see an object whose RBasic::class is exactly
rb_cClass because classes get a metaclass on boot. So there is no
ClassExact type.
This fixes the side exits on getivar-module.rb that were introduced in
a8f3c34556bac709587ded4e0e4dad08932d5900 ("ZJIT: Add missing guard
on ivar access on T_{DATA,CLASS,MODULE}"). The `GuardType v, Class` checked
for exactly rb_cClass and never passed.
| -rw-r--r-- | zjit/src/hir_type/gen_hir_type.rb | 6 | ||||
| -rw-r--r-- | zjit/src/hir_type/hir_type.inc.rs | 11 |
2 files changed, 8 insertions, 9 deletions
diff --git a/zjit/src/hir_type/gen_hir_type.rb b/zjit/src/hir_type/gen_hir_type.rb index 37919425ce..aca8e574d6 100644 --- a/zjit/src/hir_type/gen_hir_type.rb +++ b/zjit/src/hir_type/gen_hir_type.rb @@ -89,7 +89,7 @@ def base_type name, c_name: nil [type, exact] end -# Define a new type that cannot be subclassed. +# Define a new type that has no subclasses and cannot be subclassed. # If c_name is given, mark the rb_cXYZ object as equivalent to this type. def final_type name, base: $object, c_name: nil if c_name @@ -109,7 +109,9 @@ base_type "Range", c_name: "rb_cRange" base_type "Set", c_name: "rb_cSet" base_type "Regexp", c_name: "rb_cRegexp" module_class, _ = base_type "Module", c_name: "rb_cModule" -class_ = final_type "Class", base: module_class, c_name: "rb_cClass" +# Class cannot be subclassed by doing `class Sub < Class`, +# but every metaclass is a subclass of `Class`. It's not final. +module_class.subtype "Class" numeric, _ = base_type "Numeric", c_name: "rb_cNumeric" diff --git a/zjit/src/hir_type/hir_type.inc.rs b/zjit/src/hir_type/hir_type.inc.rs index f37cd57b31..46c45f17f3 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 = FalseClass | TrueClass; - pub const BuiltinExact: u64 = ArrayExact | BasicObjectExact | Class | FalseClass | Float | HashExact | Integer | ModuleExact | NilClass | NumericExact | ObjectExact | RangeExact | RegexpExact | SetExact | StringExact | Symbol | TrueClass; + pub const BuiltinExact: u64 = ArrayExact | BasicObjectExact | FalseClass | Float | HashExact | Integer | ModuleExact | NilClass | NumericExact | ObjectExact | RangeExact | RegexpExact | SetExact | StringExact | Symbol | TrueClass; pub const CBool: u64 = 1u64 << 5; pub const CDouble: u64 = 1u64 << 6; pub const CInt: u64 = CSigned | CUnsigned; @@ -231,7 +231,7 @@ pub mod types { pub const Truthy: Type = Type::from_bits(bits::Truthy); pub const TypedTData: Type = Type::from_bits(bits::TypedTData); pub const Undef: Type = Type::from_bits(bits::Undef); - pub const ExactBitsAndClass: [(u64, *const VALUE); 17] = [ + pub const ExactBitsAndClass: [(u64, *const VALUE); 16] = [ (bits::ObjectExact, &raw const crate::cruby::rb_cObject), (bits::BasicObjectExact, &raw const crate::cruby::rb_cBasicObject), (bits::StringExact, &raw const crate::cruby::rb_cString), @@ -241,7 +241,6 @@ pub mod types { (bits::SetExact, &raw const crate::cruby::rb_cSet), (bits::RegexpExact, &raw const crate::cruby::rb_cRegexp), (bits::ModuleExact, &raw const crate::cruby::rb_cModule), - (bits::Class, &raw const crate::cruby::rb_cClass), (bits::NumericExact, &raw const crate::cruby::rb_cNumeric), (bits::Integer, &raw const crate::cruby::rb_cInteger), (bits::Float, &raw const crate::cruby::rb_cFloat), @@ -250,9 +249,8 @@ pub mod types { (bits::TrueClass, &raw const crate::cruby::rb_cTrueClass), (bits::FalseClass, &raw const crate::cruby::rb_cFalseClass), ]; - pub const SubclassBitsAndClass: [(u64, *const VALUE); 17] = [ + pub const SubclassBitsAndClass: [(u64, *const VALUE); 16] = [ (bits::ArraySubclass, &raw const crate::cruby::rb_cArray), - (bits::Class, &raw const crate::cruby::rb_cClass), (bits::FalseClass, &raw const crate::cruby::rb_cFalseClass), (bits::Integer, &raw const crate::cruby::rb_cInteger), (bits::HashSubclass, &raw const crate::cruby::rb_cHash), @@ -269,9 +267,8 @@ pub mod types { (bits::ObjectSubclass, &raw const crate::cruby::rb_cObject), (bits::BasicObjectSubclass, &raw const crate::cruby::rb_cBasicObject), ]; - pub const InexactBitsAndClass: [(u64, *const VALUE); 17] = [ + pub const InexactBitsAndClass: [(u64, *const VALUE); 16] = [ (bits::Array, &raw const crate::cruby::rb_cArray), - (bits::Class, &raw const crate::cruby::rb_cClass), (bits::FalseClass, &raw const crate::cruby::rb_cFalseClass), (bits::Integer, &raw const crate::cruby::rb_cInteger), (bits::Hash, &raw const crate::cruby::rb_cHash), |
