summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Bernstein <ruby@bernsteinbear.com>2025-07-28 09:54:25 -0400
committerMax Bernstein <tekknolagi@gmail.com>2025-07-28 12:35:21 -0700
commitf6dccdb1ff271d391fa51935370e07747c5722a3 (patch)
treec10456b7f137fc24561c716cf9cc68a6a1572df1
parent043489abc2fe9a1953e19588101e469cbc505f38 (diff)
ZJIT: Remove Integer subclasses from lattice
While Integer can technically be subclassed, instances of subclasses cannot be created. Remove it from the type lattice.
-rw-r--r--zjit/src/hir_type/gen_hir_type.rb9
-rw-r--r--zjit/src/hir_type/hir_type.inc.rs56
-rw-r--r--zjit/src/hir_type/mod.rs14
3 files changed, 36 insertions, 43 deletions
diff --git a/zjit/src/hir_type/gen_hir_type.rb b/zjit/src/hir_type/gen_hir_type.rb
index 361026e101..27f936a389 100644
--- a/zjit/src/hir_type/gen_hir_type.rb
+++ b/zjit/src/hir_type/gen_hir_type.rb
@@ -68,6 +68,13 @@ def base_type name
[type, exact]
end
+# Define a new type that cannot be subclassed.
+def final_type name
+ type = $object.subtype name
+ $builtin_exact << type.name
+ type
+end
+
base_type "String"
base_type "Array"
base_type "Hash"
@@ -77,7 +84,7 @@ base_type "Regexp"
module_class, _ = base_type "Module"
module_class.subtype "Class"
-_, integer_exact = base_type "Integer"
+integer_exact = final_type "Integer"
# CRuby partitions Integer into immediate and non-immediate variants.
fixnum = integer_exact.subtype "Fixnum"
integer_exact.subtype "Bignum"
diff --git a/zjit/src/hir_type/hir_type.inc.rs b/zjit/src/hir_type/hir_type.inc.rs
index 21ef8c8bdd..aaef14467b 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 | FalseClassExact | FloatExact | HashExact | IntegerExact | ModuleExact | NilClassExact | ObjectExact | RangeExact | RegexpExact | SetExact | StringExact | SymbolExact | TrueClassExact;
+ pub const BuiltinExact: u64 = ArrayExact | BasicObjectExact | FalseClassExact | FloatExact | HashExact | Integer | 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;
@@ -43,41 +43,39 @@ mod bits {
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 << 28;
+ pub const Integer: u64 = Bignum | Fixnum;
pub const Module: u64 = Class | ModuleExact | ModuleSubclass;
- pub const ModuleExact: u64 = 1u64 << 29;
- pub const ModuleSubclass: u64 = 1u64 << 30;
+ pub const ModuleExact: u64 = 1u64 << 28;
+ pub const ModuleSubclass: u64 = 1u64 << 29;
pub const NilClass: u64 = NilClassExact | NilClassSubclass;
- pub const NilClassExact: u64 = 1u64 << 31;
- pub const NilClassSubclass: u64 = 1u64 << 32;
+ pub const NilClassExact: u64 = 1u64 << 30;
+ pub const NilClassSubclass: u64 = 1u64 << 31;
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 ObjectExact: u64 = 1u64 << 32;
+ pub const ObjectSubclass: u64 = 1u64 << 33;
pub const Range: u64 = RangeExact | RangeSubclass;
- pub const RangeExact: u64 = 1u64 << 35;
- pub const RangeSubclass: u64 = 1u64 << 36;
+ pub const RangeExact: u64 = 1u64 << 34;
+ pub const RangeSubclass: u64 = 1u64 << 35;
pub const Regexp: u64 = RegexpExact | RegexpSubclass;
- pub const RegexpExact: u64 = 1u64 << 37;
- pub const RegexpSubclass: u64 = 1u64 << 38;
+ pub const RegexpExact: u64 = 1u64 << 36;
+ pub const RegexpSubclass: u64 = 1u64 << 37;
pub const RubyValue: u64 = BasicObject | CallableMethodEntry | Undef;
pub const Set: u64 = SetExact | SetSubclass;
- pub const SetExact: u64 = 1u64 << 39;
- pub const SetSubclass: u64 = 1u64 << 40;
- pub const StaticSymbol: u64 = 1u64 << 41;
+ pub const SetExact: u64 = 1u64 << 38;
+ pub const SetSubclass: u64 = 1u64 << 39;
+ pub const StaticSymbol: u64 = 1u64 << 40;
pub const String: u64 = StringExact | StringSubclass;
- 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 StringExact: u64 = 1u64 << 41;
+ pub const StringSubclass: u64 = 1u64 << 42;
+ pub const Subclass: u64 = ArraySubclass | BasicObjectSubclass | FalseClassSubclass | FloatSubclass | HashSubclass | 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 << 44;
+ pub const SymbolSubclass: u64 = 1u64 << 43;
pub const TrueClass: u64 = TrueClassExact | TrueClassSubclass;
- 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] = [
+ pub const TrueClassExact: u64 = 1u64 << 44;
+ pub const TrueClassSubclass: u64 = 1u64 << 45;
+ pub const Undef: u64 = 1u64 << 46;
+ pub const AllBitPatterns: [(&'static str, u64); 75] = [
("Any", Any),
("RubyValue", RubyValue),
("Immediate", Immediate),
@@ -114,8 +112,6 @@ mod bits {
("Module", Module),
("ModuleSubclass", ModuleSubclass),
("ModuleExact", ModuleExact),
- ("Integer", Integer),
- ("IntegerSubclass", IntegerSubclass),
("Float", Float),
("FloatExact", FloatExact),
("HeapFloat", HeapFloat),
@@ -124,7 +120,7 @@ mod bits {
("HashExact", HashExact),
("Flonum", Flonum),
("FloatSubclass", FloatSubclass),
- ("IntegerExact", IntegerExact),
+ ("Integer", Integer),
("Fixnum", Fixnum),
("FalseClass", FalseClass),
("FalseClassSubclass", FalseClassSubclass),
@@ -156,7 +152,7 @@ mod bits {
("ArrayExact", ArrayExact),
("Empty", Empty),
];
- pub const NumTypeBits: u64 = 48;
+ pub const NumTypeBits: u64 = 47;
}
pub mod types {
use super::*;
@@ -204,8 +200,6 @@ pub mod types {
pub const HeapFloat: Type = Type::from_bits(bits::HeapFloat);
pub const Immediate: Type = Type::from_bits(bits::Immediate);
pub const Integer: Type = Type::from_bits(bits::Integer);
- pub const IntegerExact: Type = Type::from_bits(bits::IntegerExact);
- pub const IntegerSubclass: Type = Type::from_bits(bits::IntegerSubclass);
pub const Module: Type = Type::from_bits(bits::Module);
pub const ModuleExact: Type = Type::from_bits(bits::ModuleExact);
pub const ModuleSubclass: Type = Type::from_bits(bits::ModuleSubclass);
diff --git a/zjit/src/hir_type/mod.rs b/zjit/src/hir_type/mod.rs
index 35d8866844..462a84ff01 100644
--- a/zjit/src/hir_type/mod.rs
+++ b/zjit/src/hir_type/mod.rs
@@ -442,7 +442,7 @@ impl Type {
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 }); }
- if self.is_subtype(types::IntegerExact) { return Some(unsafe { rb_cInteger }); }
+ if self.is_subtype(types::Integer) { return Some(unsafe { rb_cInteger }); }
if self.is_subtype(types::ModuleExact) { return Some(unsafe { rb_cModule }); }
if self.is_subtype(types::NilClassExact) { return Some(unsafe { rb_cNilClass }); }
if self.is_subtype(types::ObjectExact) { return Some(unsafe { rb_cObject }); }
@@ -547,10 +547,8 @@ mod tests {
assert_subtype(Type::fixnum(123), Type::fixnum(123));
assert_not_subtype(Type::fixnum(123), Type::fixnum(200));
assert_subtype(Type::from_value(VALUE::fixnum_from_usize(123)), types::Fixnum);
- assert_subtype(types::Fixnum, types::IntegerExact);
- assert_subtype(types::Bignum, types::IntegerExact);
- assert_subtype(types::IntegerExact, types::Integer);
- assert_subtype(types::IntegerSubclass, types::Integer);
+ assert_subtype(types::Fixnum, types::Integer);
+ assert_subtype(types::Bignum, types::Integer);
}
#[test]
@@ -590,7 +588,6 @@ mod tests {
fn fixnum_has_ruby_object() {
assert_eq!(Type::fixnum(3).ruby_object(), Some(VALUE::fixnum_from_usize(3)));
assert_eq!(types::Fixnum.ruby_object(), None);
- assert_eq!(types::IntegerExact.ruby_object(), None);
assert_eq!(types::Integer.ruby_object(), None);
}
@@ -608,7 +605,6 @@ mod tests {
fn integer_has_exact_ruby_class() {
assert_eq!(Type::fixnum(3).exact_ruby_class(), Some(unsafe { rb_cInteger }.into()));
assert_eq!(types::Fixnum.exact_ruby_class(), None);
- assert_eq!(types::IntegerExact.exact_ruby_class(), None);
assert_eq!(types::Integer.exact_ruby_class(), None);
}
@@ -636,7 +632,6 @@ mod tests {
fn integer_has_ruby_class() {
assert_eq!(Type::fixnum(3).inexact_ruby_class(), Some(unsafe { rb_cInteger }.into()));
assert_eq!(types::Fixnum.inexact_ruby_class(), None);
- assert_eq!(types::IntegerExact.inexact_ruby_class(), None);
assert_eq!(types::Integer.inexact_ruby_class(), None);
}
@@ -670,7 +665,6 @@ mod tests {
assert_eq!(format!("{}", Type::from_cbool(false)), "CBool[false]");
assert_eq!(format!("{}", types::Fixnum), "Fixnum");
assert_eq!(format!("{}", types::Integer), "Integer");
- assert_eq!(format!("{}", types::IntegerExact), "IntegerExact");
}
#[test]
@@ -688,12 +682,10 @@ mod tests {
#[test]
fn union_bits_subtype() {
- assert_bit_equal(types::Fixnum.union(types::IntegerExact), types::IntegerExact);
assert_bit_equal(types::Fixnum.union(types::Integer), types::Integer);
assert_bit_equal(types::Fixnum.union(types::Object), types::Object);
assert_bit_equal(Type::fixnum(3).union(types::Fixnum), types::Fixnum);
- assert_bit_equal(types::IntegerExact.union(types::Fixnum), types::IntegerExact);
assert_bit_equal(types::Integer.union(types::Fixnum), types::Integer);
assert_bit_equal(types::Object.union(types::Fixnum), types::Object);
assert_bit_equal(types::Fixnum.union(Type::fixnum(3)), types::Fixnum);