ZJIT: Add CallableMethodEntry to type lattice (GH-13459)
This will be useful when we split Send into Lookup+Call. For reasoning about various method types during optimization.
This commit is contained in:
parent
b5f5672034
commit
9a1d6cc799
@ -573,6 +573,11 @@ impl VALUE {
|
|||||||
ptr
|
ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cme_p(self) -> bool {
|
||||||
|
if self == VALUE(0) { return false; }
|
||||||
|
unsafe { rb_IMEMO_TYPE_P(self, imemo_ment) == 1 }
|
||||||
|
}
|
||||||
|
|
||||||
/// Assert that `self` is a method entry in debug builds
|
/// Assert that `self` is a method entry in debug builds
|
||||||
pub fn as_cme(self) -> *const rb_callable_method_entry_t {
|
pub fn as_cme(self) -> *const rb_callable_method_entry_t {
|
||||||
let ptr: *const rb_callable_method_entry_t = self.as_ptr();
|
let ptr: *const rb_callable_method_entry_t = self.as_ptr();
|
||||||
|
@ -48,6 +48,7 @@ any = Type.new "Any"
|
|||||||
# Build the Ruby object universe.
|
# Build the Ruby object universe.
|
||||||
value = any.subtype "RubyValue"
|
value = any.subtype "RubyValue"
|
||||||
undef_ = value.subtype "Undef"
|
undef_ = value.subtype "Undef"
|
||||||
|
value.subtype "CallableMethodEntry" # rb_callable_method_entry_t*
|
||||||
basic_object = value.subtype "BasicObject"
|
basic_object = value.subtype "BasicObject"
|
||||||
basic_object_exact = basic_object.subtype "BasicObjectExact"
|
basic_object_exact = basic_object.subtype "BasicObjectExact"
|
||||||
basic_object_subclass = basic_object.subtype "BasicObjectSubclass"
|
basic_object_subclass = basic_object.subtype "BasicObjectSubclass"
|
||||||
|
51
zjit/src/hir_type/hir_type.inc.rs
generated
51
zjit/src/hir_type/hir_type.inc.rs
generated
@ -26,44 +26,45 @@ mod bits {
|
|||||||
pub const CUInt8: u64 = 1u64 << 16;
|
pub const CUInt8: u64 = 1u64 << 16;
|
||||||
pub const CUnsigned: u64 = CUInt16 | CUInt32 | CUInt64 | CUInt8;
|
pub const CUnsigned: u64 = CUInt16 | CUInt32 | CUInt64 | CUInt8;
|
||||||
pub const CValue: u64 = CBool | CDouble | CInt | CNull | CPtr;
|
pub const CValue: u64 = CBool | CDouble | CInt | CNull | CPtr;
|
||||||
pub const DynamicSymbol: u64 = 1u64 << 17;
|
pub const CallableMethodEntry: u64 = 1u64 << 17;
|
||||||
|
pub const DynamicSymbol: u64 = 1u64 << 18;
|
||||||
pub const Empty: u64 = 0u64;
|
pub const Empty: u64 = 0u64;
|
||||||
pub const FalseClass: u64 = FalseClassExact | FalseClassSubclass;
|
pub const FalseClass: u64 = FalseClassExact | FalseClassSubclass;
|
||||||
pub const FalseClassExact: u64 = 1u64 << 18;
|
pub const FalseClassExact: u64 = 1u64 << 19;
|
||||||
pub const FalseClassSubclass: u64 = 1u64 << 19;
|
pub const FalseClassSubclass: u64 = 1u64 << 20;
|
||||||
pub const Fixnum: u64 = 1u64 << 20;
|
pub const Fixnum: u64 = 1u64 << 21;
|
||||||
pub const Float: u64 = FloatExact | FloatSubclass;
|
pub const Float: u64 = FloatExact | FloatSubclass;
|
||||||
pub const FloatExact: u64 = Flonum | HeapFloat;
|
pub const FloatExact: u64 = Flonum | HeapFloat;
|
||||||
pub const FloatSubclass: u64 = 1u64 << 21;
|
pub const FloatSubclass: u64 = 1u64 << 22;
|
||||||
pub const Flonum: u64 = 1u64 << 22;
|
pub const Flonum: u64 = 1u64 << 23;
|
||||||
pub const Hash: u64 = HashExact | HashSubclass;
|
pub const Hash: u64 = HashExact | HashSubclass;
|
||||||
pub const HashExact: u64 = 1u64 << 23;
|
pub const HashExact: u64 = 1u64 << 24;
|
||||||
pub const HashSubclass: u64 = 1u64 << 24;
|
pub const HashSubclass: u64 = 1u64 << 25;
|
||||||
pub const HeapFloat: u64 = 1u64 << 25;
|
pub const HeapFloat: u64 = 1u64 << 26;
|
||||||
pub const Immediate: u64 = FalseClassExact | Fixnum | Flonum | NilClassExact | StaticSymbol | TrueClassExact | Undef;
|
pub const Immediate: u64 = FalseClassExact | Fixnum | Flonum | NilClassExact | StaticSymbol | TrueClassExact | Undef;
|
||||||
pub const Integer: u64 = IntegerExact | IntegerSubclass;
|
pub const Integer: u64 = IntegerExact | IntegerSubclass;
|
||||||
pub const IntegerExact: u64 = Bignum | Fixnum;
|
pub const IntegerExact: u64 = Bignum | Fixnum;
|
||||||
pub const IntegerSubclass: u64 = 1u64 << 26;
|
pub const IntegerSubclass: u64 = 1u64 << 27;
|
||||||
pub const NilClass: u64 = NilClassExact | NilClassSubclass;
|
pub const NilClass: u64 = NilClassExact | NilClassSubclass;
|
||||||
pub const NilClassExact: u64 = 1u64 << 27;
|
pub const NilClassExact: u64 = 1u64 << 28;
|
||||||
pub const NilClassSubclass: u64 = 1u64 << 28;
|
pub const NilClassSubclass: u64 = 1u64 << 29;
|
||||||
pub const Object: u64 = Array | FalseClass | Float | Hash | Integer | NilClass | ObjectExact | ObjectSubclass | String | Symbol | TrueClass;
|
pub const Object: u64 = Array | FalseClass | Float | Hash | Integer | NilClass | ObjectExact | ObjectSubclass | String | Symbol | TrueClass;
|
||||||
pub const ObjectExact: u64 = 1u64 << 29;
|
pub const ObjectExact: u64 = 1u64 << 30;
|
||||||
pub const ObjectSubclass: u64 = 1u64 << 30;
|
pub const ObjectSubclass: u64 = 1u64 << 31;
|
||||||
pub const RubyValue: u64 = BasicObject | Undef;
|
pub const RubyValue: u64 = BasicObject | CallableMethodEntry | Undef;
|
||||||
pub const StaticSymbol: u64 = 1u64 << 31;
|
pub const StaticSymbol: u64 = 1u64 << 32;
|
||||||
pub const String: u64 = StringExact | StringSubclass;
|
pub const String: u64 = StringExact | StringSubclass;
|
||||||
pub const StringExact: u64 = 1u64 << 32;
|
pub const StringExact: u64 = 1u64 << 33;
|
||||||
pub const StringSubclass: u64 = 1u64 << 33;
|
pub const StringSubclass: u64 = 1u64 << 34;
|
||||||
pub const Subclass: u64 = ArraySubclass | BasicObjectSubclass | FalseClassSubclass | FloatSubclass | HashSubclass | IntegerSubclass | NilClassSubclass | ObjectSubclass | StringSubclass | SymbolSubclass | TrueClassSubclass;
|
pub const Subclass: u64 = ArraySubclass | BasicObjectSubclass | FalseClassSubclass | FloatSubclass | HashSubclass | IntegerSubclass | NilClassSubclass | ObjectSubclass | StringSubclass | SymbolSubclass | TrueClassSubclass;
|
||||||
pub const Symbol: u64 = SymbolExact | SymbolSubclass;
|
pub const Symbol: u64 = SymbolExact | SymbolSubclass;
|
||||||
pub const SymbolExact: u64 = DynamicSymbol | StaticSymbol;
|
pub const SymbolExact: u64 = DynamicSymbol | StaticSymbol;
|
||||||
pub const SymbolSubclass: u64 = 1u64 << 34;
|
pub const SymbolSubclass: u64 = 1u64 << 35;
|
||||||
pub const TrueClass: u64 = TrueClassExact | TrueClassSubclass;
|
pub const TrueClass: u64 = TrueClassExact | TrueClassSubclass;
|
||||||
pub const TrueClassExact: u64 = 1u64 << 35;
|
pub const TrueClassExact: u64 = 1u64 << 36;
|
||||||
pub const TrueClassSubclass: u64 = 1u64 << 36;
|
pub const TrueClassSubclass: u64 = 1u64 << 37;
|
||||||
pub const Undef: u64 = 1u64 << 37;
|
pub const Undef: u64 = 1u64 << 38;
|
||||||
pub const AllBitPatterns: [(&'static str, u64); 63] = [
|
pub const AllBitPatterns: [(&'static str, u64); 64] = [
|
||||||
("Any", Any),
|
("Any", Any),
|
||||||
("RubyValue", RubyValue),
|
("RubyValue", RubyValue),
|
||||||
("Immediate", Immediate),
|
("Immediate", Immediate),
|
||||||
@ -104,6 +105,7 @@ mod bits {
|
|||||||
("FalseClassSubclass", FalseClassSubclass),
|
("FalseClassSubclass", FalseClassSubclass),
|
||||||
("FalseClassExact", FalseClassExact),
|
("FalseClassExact", FalseClassExact),
|
||||||
("DynamicSymbol", DynamicSymbol),
|
("DynamicSymbol", DynamicSymbol),
|
||||||
|
("CallableMethodEntry", CallableMethodEntry),
|
||||||
("CValue", CValue),
|
("CValue", CValue),
|
||||||
("CInt", CInt),
|
("CInt", CInt),
|
||||||
("CUnsigned", CUnsigned),
|
("CUnsigned", CUnsigned),
|
||||||
@ -128,7 +130,7 @@ mod bits {
|
|||||||
("ArrayExact", ArrayExact),
|
("ArrayExact", ArrayExact),
|
||||||
("Empty", Empty),
|
("Empty", Empty),
|
||||||
];
|
];
|
||||||
pub const NumTypeBits: u64 = 38;
|
pub const NumTypeBits: u64 = 39;
|
||||||
}
|
}
|
||||||
pub mod types {
|
pub mod types {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -158,6 +160,7 @@ pub mod types {
|
|||||||
pub const CUInt8: Type = Type::from_bits(bits::CUInt8);
|
pub const CUInt8: Type = Type::from_bits(bits::CUInt8);
|
||||||
pub const CUnsigned: Type = Type::from_bits(bits::CUnsigned);
|
pub const CUnsigned: Type = Type::from_bits(bits::CUnsigned);
|
||||||
pub const CValue: Type = Type::from_bits(bits::CValue);
|
pub const CValue: Type = Type::from_bits(bits::CValue);
|
||||||
|
pub const CallableMethodEntry: Type = Type::from_bits(bits::CallableMethodEntry);
|
||||||
pub const DynamicSymbol: Type = Type::from_bits(bits::DynamicSymbol);
|
pub const DynamicSymbol: Type = Type::from_bits(bits::DynamicSymbol);
|
||||||
pub const Empty: Type = Type::from_bits(bits::Empty);
|
pub const Empty: Type = Type::from_bits(bits::Empty);
|
||||||
pub const FalseClass: Type = Type::from_bits(bits::FalseClass);
|
pub const FalseClass: Type = Type::from_bits(bits::FalseClass);
|
||||||
|
@ -163,6 +163,11 @@ impl Type {
|
|||||||
else if val == Qnil { types::NilClassExact }
|
else if val == Qnil { types::NilClassExact }
|
||||||
else if val == Qtrue { types::TrueClassExact }
|
else if val == Qtrue { types::TrueClassExact }
|
||||||
else if val == Qfalse { types::FalseClassExact }
|
else if val == Qfalse { types::FalseClassExact }
|
||||||
|
else if val.cme_p() {
|
||||||
|
// NB: Checking for CME has to happen before looking at class_of because that's not
|
||||||
|
// valid on imemo.
|
||||||
|
Type { bits: bits::CallableMethodEntry, spec: Specialization::Object(val) }
|
||||||
|
}
|
||||||
else if val.class_of() == unsafe { rb_cInteger } {
|
else if val.class_of() == unsafe { rb_cInteger } {
|
||||||
Type { bits: bits::Bignum, spec: Specialization::Object(val) }
|
Type { bits: bits::Bignum, spec: Specialization::Object(val) }
|
||||||
}
|
}
|
||||||
@ -682,6 +687,19 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cme() {
|
||||||
|
use crate::cruby::{rb_callable_method_entry, ID};
|
||||||
|
crate::cruby::with_rubyvm(|| {
|
||||||
|
let cme = unsafe { rb_callable_method_entry(rb_cInteger, ID!(to_s)) };
|
||||||
|
assert!(!cme.is_null());
|
||||||
|
let cme_value: VALUE = cme.into();
|
||||||
|
let ty = Type::from_value(cme_value);
|
||||||
|
assert_subtype(ty, types::CallableMethodEntry);
|
||||||
|
assert!(ty.ruby_object_known());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn union_specialized_with_no_relation_returns_unspecialized() {
|
fn union_specialized_with_no_relation_returns_unspecialized() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
crate::cruby::with_rubyvm(|| {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user