mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
ZJIT: Create HeapObject Type (#14140)
This is a counterpoint to the Immediate type and it represents all BasicObject subclasses except for the several immediate objects. If we know something is a HeapObject, we know we can treat it as an RBasic pointer.
This commit is contained in:
parent
1aabd2cb36
commit
363ad0ad17
4 changed files with 44 additions and 12 deletions
|
@ -5566,7 +5566,7 @@ mod opt_tests {
|
|||
fn test@<compiled>:5:
|
||||
bb0(v0:BasicObject):
|
||||
PatchPoint MethodRedefined(Object@0x1000, foo@0x1008, cme:0x1010)
|
||||
v6:BasicObject[class_exact*:Object@VALUE(0x1000)] = GuardType v0, BasicObject[class_exact*:Object@VALUE(0x1000)]
|
||||
v6:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v0, HeapObject[class_exact*:Object@VALUE(0x1000)]
|
||||
v7:BasicObject = SendWithoutBlockDirect v6, :foo (0x1038)
|
||||
Return v7
|
||||
"#]]);
|
||||
|
@ -5606,7 +5606,7 @@ mod opt_tests {
|
|||
fn test@<compiled>:6:
|
||||
bb0(v0:BasicObject):
|
||||
PatchPoint MethodRedefined(Object@0x1000, foo@0x1008, cme:0x1010)
|
||||
v6:BasicObject[class_exact*:Object@VALUE(0x1000)] = GuardType v0, BasicObject[class_exact*:Object@VALUE(0x1000)]
|
||||
v6:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v0, HeapObject[class_exact*:Object@VALUE(0x1000)]
|
||||
v7:BasicObject = SendWithoutBlockDirect v6, :foo (0x1038)
|
||||
Return v7
|
||||
"#]]);
|
||||
|
@ -5625,7 +5625,7 @@ mod opt_tests {
|
|||
bb0(v0:BasicObject):
|
||||
v2:Fixnum[3] = Const Value(3)
|
||||
PatchPoint MethodRedefined(Object@0x1000, Integer@0x1008, cme:0x1010)
|
||||
v7:BasicObject[class_exact*:Object@VALUE(0x1000)] = GuardType v0, BasicObject[class_exact*:Object@VALUE(0x1000)]
|
||||
v7:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v0, HeapObject[class_exact*:Object@VALUE(0x1000)]
|
||||
v8:BasicObject = SendWithoutBlockDirect v7, :Integer (0x1038), v2
|
||||
Return v8
|
||||
"#]]);
|
||||
|
@ -5647,7 +5647,7 @@ mod opt_tests {
|
|||
v2:Fixnum[1] = Const Value(1)
|
||||
v3:Fixnum[2] = Const Value(2)
|
||||
PatchPoint MethodRedefined(Object@0x1000, foo@0x1008, cme:0x1010)
|
||||
v8:BasicObject[class_exact*:Object@VALUE(0x1000)] = GuardType v0, BasicObject[class_exact*:Object@VALUE(0x1000)]
|
||||
v8:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v0, HeapObject[class_exact*:Object@VALUE(0x1000)]
|
||||
v9:BasicObject = SendWithoutBlockDirect v8, :foo (0x1038), v2, v3
|
||||
Return v9
|
||||
"#]]);
|
||||
|
@ -5670,10 +5670,10 @@ mod opt_tests {
|
|||
fn test@<compiled>:7:
|
||||
bb0(v0:BasicObject):
|
||||
PatchPoint MethodRedefined(Object@0x1000, foo@0x1008, cme:0x1010)
|
||||
v8:BasicObject[class_exact*:Object@VALUE(0x1000)] = GuardType v0, BasicObject[class_exact*:Object@VALUE(0x1000)]
|
||||
v8:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v0, HeapObject[class_exact*:Object@VALUE(0x1000)]
|
||||
v9:BasicObject = SendWithoutBlockDirect v8, :foo (0x1038)
|
||||
PatchPoint MethodRedefined(Object@0x1000, bar@0x1040, cme:0x1048)
|
||||
v11:BasicObject[class_exact*:Object@VALUE(0x1000)] = GuardType v0, BasicObject[class_exact*:Object@VALUE(0x1000)]
|
||||
v11:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v0, HeapObject[class_exact*:Object@VALUE(0x1000)]
|
||||
v12:BasicObject = SendWithoutBlockDirect v11, :bar (0x1038)
|
||||
Return v12
|
||||
"#]]);
|
||||
|
@ -6475,7 +6475,7 @@ mod opt_tests {
|
|||
fn test@<compiled>:8:
|
||||
bb0(v0:BasicObject, v1:BasicObject):
|
||||
PatchPoint MethodRedefined(C@0x1000, foo@0x1008, cme:0x1010)
|
||||
v7:BasicObject[class_exact:C] = GuardType v1, BasicObject[class_exact:C]
|
||||
v7:HeapObject[class_exact:C] = GuardType v1, HeapObject[class_exact:C]
|
||||
v8:BasicObject = SendWithoutBlockDirect v7, :foo (0x1038)
|
||||
Return v8
|
||||
"#]]);
|
||||
|
@ -7428,7 +7428,7 @@ mod opt_tests {
|
|||
fn test@<compiled>:3:
|
||||
bb0(v0:BasicObject):
|
||||
PatchPoint MethodRedefined(Object@0x1000, foo@0x1008, cme:0x1010)
|
||||
v6:BasicObject[class_exact*:Object@VALUE(0x1000)] = GuardType v0, BasicObject[class_exact*:Object@VALUE(0x1000)]
|
||||
v6:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v0, HeapObject[class_exact*:Object@VALUE(0x1000)]
|
||||
v7:BasicObject = SendWithoutBlockDirect v6, :foo (0x1038)
|
||||
Return v7
|
||||
"#]]);
|
||||
|
@ -7497,7 +7497,7 @@ mod opt_tests {
|
|||
fn test@<compiled>:6:
|
||||
bb0(v0:BasicObject, v1:BasicObject):
|
||||
PatchPoint MethodRedefined(C@0x1000, foo@0x1008, cme:0x1010)
|
||||
v7:BasicObject[class_exact:C] = GuardType v1, BasicObject[class_exact:C]
|
||||
v7:HeapObject[class_exact:C] = GuardType v1, HeapObject[class_exact:C]
|
||||
v8:BasicObject = GetIvar v7, :@foo
|
||||
Return v8
|
||||
"#]]);
|
||||
|
@ -7518,7 +7518,7 @@ mod opt_tests {
|
|||
fn test@<compiled>:6:
|
||||
bb0(v0:BasicObject, v1:BasicObject):
|
||||
PatchPoint MethodRedefined(C@0x1000, foo@0x1008, cme:0x1010)
|
||||
v7:BasicObject[class_exact:C] = GuardType v1, BasicObject[class_exact:C]
|
||||
v7:HeapObject[class_exact:C] = GuardType v1, HeapObject[class_exact:C]
|
||||
v8:BasicObject = GetIvar v7, :@foo
|
||||
Return v8
|
||||
"#]]);
|
||||
|
|
|
@ -156,6 +156,8 @@ add_union "BuiltinExact", $builtin_exact
|
|||
add_union "Subclass", $subclass
|
||||
add_union "BoolExact", [true_exact.name, false_exact.name]
|
||||
add_union "Immediate", [fixnum.name, flonum.name, static_sym.name, nil_exact.name, true_exact.name, false_exact.name, undef_.name]
|
||||
$bits["HeapObject"] = ["BasicObject & !Immediate"]
|
||||
$numeric_bits["HeapObject"] = $numeric_bits["BasicObject"] & ~$numeric_bits["Immediate"]
|
||||
|
||||
# ===== Finished generating the DAG; write Rust code =====
|
||||
|
||||
|
|
5
zjit/src/hir_type/hir_type.inc.rs
generated
5
zjit/src/hir_type/hir_type.inc.rs
generated
|
@ -38,6 +38,7 @@ mod bits {
|
|||
pub const HashExact: u64 = 1u64 << 23;
|
||||
pub const HashSubclass: u64 = 1u64 << 24;
|
||||
pub const HeapFloat: u64 = 1u64 << 25;
|
||||
pub const HeapObject: u64 = BasicObject & !Immediate;
|
||||
pub const Immediate: u64 = FalseClass | Fixnum | Flonum | NilClass | StaticSymbol | TrueClass | Undef;
|
||||
pub const Integer: u64 = Bignum | Fixnum;
|
||||
pub const Module: u64 = Class | ModuleExact | ModuleSubclass;
|
||||
|
@ -65,7 +66,7 @@ mod bits {
|
|||
pub const Symbol: u64 = DynamicSymbol | StaticSymbol;
|
||||
pub const TrueClass: u64 = 1u64 << 40;
|
||||
pub const Undef: u64 = 1u64 << 41;
|
||||
pub const AllBitPatterns: [(&'static str, u64); 65] = [
|
||||
pub const AllBitPatterns: [(&'static str, u64); 66] = [
|
||||
("Any", Any),
|
||||
("RubyValue", RubyValue),
|
||||
("Immediate", Immediate),
|
||||
|
@ -75,6 +76,7 @@ mod bits {
|
|||
("BuiltinExact", BuiltinExact),
|
||||
("BoolExact", BoolExact),
|
||||
("TrueClass", TrueClass),
|
||||
("HeapObject", HeapObject),
|
||||
("String", String),
|
||||
("Subclass", Subclass),
|
||||
("StringSubclass", StringSubclass),
|
||||
|
@ -174,6 +176,7 @@ pub mod types {
|
|||
pub const HashExact: Type = Type::from_bits(bits::HashExact);
|
||||
pub const HashSubclass: Type = Type::from_bits(bits::HashSubclass);
|
||||
pub const HeapFloat: Type = Type::from_bits(bits::HeapFloat);
|
||||
pub const HeapObject: Type = Type::from_bits(bits::HeapObject);
|
||||
pub const Immediate: Type = Type::from_bits(bits::Immediate);
|
||||
pub const Integer: Type = Type::from_bits(bits::Integer);
|
||||
pub const Module: Type = Type::from_bits(bits::Module);
|
||||
|
|
|
@ -248,7 +248,7 @@ impl Type {
|
|||
else if val.class() == unsafe { rb_cString } { types::StringExact }
|
||||
else {
|
||||
// TODO(max): Add more cases for inferring type bits from built-in types
|
||||
Type { bits: bits::BasicObject, spec: Specialization::TypeExact(val.class()) }
|
||||
Type { bits: bits::HeapObject, spec: Specialization::TypeExact(val.class()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -583,6 +583,7 @@ mod tests {
|
|||
assert_subtype(Type::fixnum(123), types::Immediate);
|
||||
assert_subtype(types::Fixnum, types::Immediate);
|
||||
assert_not_subtype(types::Bignum, types::Immediate);
|
||||
assert_not_subtype(types::Integer, types::Immediate);
|
||||
assert_subtype(types::NilClass, types::Immediate);
|
||||
assert_subtype(types::TrueClass, types::Immediate);
|
||||
assert_subtype(types::FalseClass, types::Immediate);
|
||||
|
@ -592,6 +593,32 @@ mod tests {
|
|||
assert_not_subtype(types::HeapFloat, types::Immediate);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn heap_object() {
|
||||
assert_not_subtype(Type::fixnum(123), types::HeapObject);
|
||||
assert_not_subtype(types::Fixnum, types::HeapObject);
|
||||
assert_subtype(types::Bignum, types::HeapObject);
|
||||
assert_not_subtype(types::Integer, types::HeapObject);
|
||||
assert_not_subtype(types::NilClass, types::HeapObject);
|
||||
assert_not_subtype(types::TrueClass, types::HeapObject);
|
||||
assert_not_subtype(types::FalseClass, types::HeapObject);
|
||||
assert_not_subtype(types::StaticSymbol, types::HeapObject);
|
||||
assert_subtype(types::DynamicSymbol, types::HeapObject);
|
||||
assert_not_subtype(types::Flonum, types::HeapObject);
|
||||
assert_subtype(types::HeapFloat, types::HeapObject);
|
||||
assert_not_subtype(types::BasicObject, types::HeapObject);
|
||||
assert_not_subtype(types::Object, types::HeapObject);
|
||||
assert_not_subtype(types::Immediate, types::HeapObject);
|
||||
assert_not_subtype(types::HeapObject, types::Immediate);
|
||||
crate::cruby::with_rubyvm(|| {
|
||||
let left = Type::from_value(rust_str_to_ruby("hello"));
|
||||
let right = Type::from_value(rust_str_to_ruby("world"));
|
||||
assert_subtype(left, types::HeapObject);
|
||||
assert_subtype(right, types::HeapObject);
|
||||
assert_subtype(left.union(right), types::HeapObject);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fixnum_has_ruby_object() {
|
||||
assert_eq!(Type::fixnum(3).ruby_object(), Some(VALUE::fixnum_from_usize(3)));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue