Skip to content

Commit de92dd9

Browse files
authored
ZJIT: Add Ruby class objects to HIR type lattice automatically (ruby#14647)
This: * gets us out of the business of manually writing a bunch of `if`s * gets us more type information * cleans up the code * also adds `types::Numeric`
1 parent d869164 commit de92dd9

File tree

4 files changed

+171
-142
lines changed

4 files changed

+171
-142
lines changed

zjit/src/hir.rs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,10 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
829829
Insn::ArrayDup { val, .. } => { write!(f, "ArrayDup {val}") }
830830
Insn::HashDup { val, .. } => { write!(f, "HashDup {val}") }
831831
Insn::ObjectAlloc { val, .. } => { write!(f, "ObjectAlloc {val}") }
832-
Insn::ObjectAllocClass { class, .. } => { write!(f, "ObjectAllocClass {}", class.print(self.ptr_map)) }
832+
&Insn::ObjectAllocClass { class, .. } => {
833+
let class_name = get_class_name(class);
834+
write!(f, "ObjectAllocClass {class_name}:{}", class.print(self.ptr_map))
835+
}
833836
Insn::StringCopy { val, .. } => { write!(f, "StringCopy {val}") }
834837
Insn::StringConcat { strings, .. } => {
835838
write!(f, "StringConcat")?;
@@ -5637,7 +5640,7 @@ mod tests {
56375640
v10:ArrayExact = ToArray v2
56385641
PatchPoint NoEPEscape(test)
56395642
GuardBlockParamProxy l0
5640-
v15:BasicObject[BlockParamProxy] = Const Value(VALUE(0x1000))
5643+
v15:HeapObject[BlockParamProxy] = Const Value(VALUE(0x1000))
56415644
SideExit UnhandledYARVInsn(splatkw)
56425645
");
56435646
}
@@ -6221,16 +6224,16 @@ mod tests {
62216224
v10:BasicObject = InvokeBuiltin dir_s_open, v0, v1, v2
62226225
PatchPoint NoEPEscape(open)
62236226
GuardBlockParamProxy l0
6224-
v17:BasicObject[BlockParamProxy] = Const Value(VALUE(0x1000))
6227+
v17:HeapObject[BlockParamProxy] = Const Value(VALUE(0x1000))
62256228
CheckInterrupts
6226-
v20:CBool = Test v17
6229+
v20:CBool[true] = Test v17
62276230
IfFalse v20, bb1(v0, v1, v2, v3, v4, v10)
62286231
PatchPoint NoEPEscape(open)
62296232
v27:BasicObject = InvokeBlock, v10
62306233
v31:BasicObject = InvokeBuiltin dir_s_close, v0, v10
62316234
CheckInterrupts
62326235
Return v27
6233-
bb1(v37:BasicObject, v38:BasicObject, v39:BasicObject, v40:BasicObject, v41:BasicObject, v42:BasicObject):
6236+
bb1(v37, v38, v39, v40, v41, v42):
62346237
PatchPoint NoEPEscape(open)
62356238
CheckInterrupts
62366239
Return v42
@@ -8033,7 +8036,7 @@ mod opt_tests {
80338036
bb0(v0:BasicObject):
80348037
PatchPoint SingleRactorMode
80358038
PatchPoint StableConstantNames(0x1000, MY_MODULE)
8036-
v13:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
8039+
v13:HeapObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
80378040
CheckInterrupts
80388041
Return v13
80398042
");
@@ -8378,7 +8381,7 @@ mod opt_tests {
83788381
v34:Class[VALUE(0x1008)] = Const Value(VALUE(0x1008))
83798382
v6:NilClass = Const Value(nil)
83808383
PatchPoint MethodRedefined(C@0x1008, new@0x1010, cme:0x1018)
8381-
v37:HeapObject[class_exact:C] = ObjectAllocClass VALUE(0x1008)
8384+
v37:HeapObject[class_exact:C] = ObjectAllocClass C:VALUE(0x1008)
83828385
PatchPoint MethodRedefined(C@0x1008, initialize@0x1040, cme:0x1048)
83838386
v39:NilClass = CCall initialize@0x1070, v37
83848387
CheckInterrupts
@@ -8407,7 +8410,7 @@ mod opt_tests {
84078410
v6:NilClass = Const Value(nil)
84088411
v7:Fixnum[1] = Const Value(1)
84098412
PatchPoint MethodRedefined(C@0x1008, new@0x1010, cme:0x1018)
8410-
v39:HeapObject[class_exact:C] = ObjectAllocClass VALUE(0x1008)
8413+
v39:HeapObject[class_exact:C] = ObjectAllocClass C:VALUE(0x1008)
84118414
PatchPoint MethodRedefined(C@0x1008, initialize@0x1040, cme:0x1048)
84128415
v41:BasicObject = SendWithoutBlockDirect v39, :initialize (0x1070), v7
84138416
CheckInterrupts
@@ -8430,7 +8433,7 @@ mod opt_tests {
84308433
v34:Class[VALUE(0x1008)] = Const Value(VALUE(0x1008))
84318434
v6:NilClass = Const Value(nil)
84328435
PatchPoint MethodRedefined(Object@0x1008, new@0x1010, cme:0x1018)
8433-
v37:HeapObject[class_exact:Object] = ObjectAllocClass VALUE(0x1008)
8436+
v37:ObjectExact = ObjectAllocClass Object:VALUE(0x1008)
84348437
PatchPoint MethodRedefined(Object@0x1008, initialize@0x1040, cme:0x1048)
84358438
v39:NilClass = CCall initialize@0x1070, v37
84368439
CheckInterrupts
@@ -8453,7 +8456,7 @@ mod opt_tests {
84538456
v34:Class[VALUE(0x1008)] = Const Value(VALUE(0x1008))
84548457
v6:NilClass = Const Value(nil)
84558458
PatchPoint MethodRedefined(BasicObject@0x1008, new@0x1010, cme:0x1018)
8456-
v37:HeapObject[class_exact:BasicObject] = ObjectAllocClass VALUE(0x1008)
8459+
v37:BasicObjectExact = ObjectAllocClass BasicObject:VALUE(0x1008)
84578460
PatchPoint MethodRedefined(BasicObject@0x1008, initialize@0x1040, cme:0x1048)
84588461
v39:NilClass = CCall initialize@0x1070, v37
84598462
CheckInterrupts
@@ -8476,7 +8479,7 @@ mod opt_tests {
84768479
v34:Class[VALUE(0x1008)] = Const Value(VALUE(0x1008))
84778480
v6:NilClass = Const Value(nil)
84788481
PatchPoint MethodRedefined(Hash@0x1008, new@0x1010, cme:0x1018)
8479-
v37:HashExact = ObjectAllocClass VALUE(0x1008)
8482+
v37:HashExact = ObjectAllocClass Hash:VALUE(0x1008)
84808483
v12:BasicObject = SendWithoutBlock v37, :initialize
84818484
CheckInterrupts
84828485
CheckInterrupts
@@ -8523,7 +8526,7 @@ mod opt_tests {
85238526
PatchPoint MethodRedefined(Set@0x1008, new@0x1010, cme:0x1018)
85248527
v10:HeapObject = ObjectAlloc v34
85258528
PatchPoint MethodRedefined(Set@0x1008, initialize@0x1040, cme:0x1048)
8526-
v39:HeapObject[class_exact:Set] = GuardType v10, HeapObject[class_exact:Set]
8529+
v39:SetExact = GuardType v10, SetExact
85278530
v40:BasicObject = CCallVariadic initialize@0x1070, v39
85288531
CheckInterrupts
85298532
CheckInterrupts
@@ -8568,7 +8571,7 @@ mod opt_tests {
85688571
v7:StringExact[VALUE(0x1010)] = Const Value(VALUE(0x1010))
85698572
v9:StringExact = StringCopy v7
85708573
PatchPoint MethodRedefined(Regexp@0x1008, new@0x1018, cme:0x1020)
8571-
v41:HeapObject[class_exact:Regexp] = ObjectAllocClass VALUE(0x1008)
8574+
v41:RegexpExact = ObjectAllocClass Regexp:VALUE(0x1008)
85728575
PatchPoint MethodRedefined(Regexp@0x1008, initialize@0x1048, cme:0x1050)
85738576
v44:BasicObject = CCallVariadic initialize@0x1078, v41, v9
85748577
CheckInterrupts
@@ -8618,7 +8621,7 @@ mod opt_tests {
86188621
fn test@<compiled>:2:
86198622
bb0(v0:BasicObject, v1:BasicObject):
86208623
GuardBlockParamProxy l0
8621-
v7:BasicObject[BlockParamProxy] = Const Value(VALUE(0x1000))
8624+
v7:HeapObject[BlockParamProxy] = Const Value(VALUE(0x1000))
86228625
v9:BasicObject = Send v0, 0x1008, :tap, v7
86238626
CheckInterrupts
86248627
Return v9
@@ -9632,10 +9635,9 @@ mod opt_tests {
96329635
bb0(v0:BasicObject):
96339636
PatchPoint SingleRactorMode
96349637
PatchPoint StableConstantNames(0x1000, O)
9635-
v15:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
9638+
v15:HeapObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
96369639
PatchPoint MethodRedefined(C@0x1010, foo@0x1018, cme:0x1020)
9637-
v18:HeapObject[VALUE(0x1008)] = GuardType v15, HeapObject
9638-
v19:HeapObject[VALUE(0x1008)] = GuardShape v18, 0x1048
9640+
v19:HeapObject[VALUE(0x1008)] = GuardShape v15, 0x1048
96399641
v20:NilClass = Const Value(nil)
96409642
CheckInterrupts
96419643
Return v20
@@ -9659,10 +9661,9 @@ mod opt_tests {
96599661
bb0(v0:BasicObject):
96609662
PatchPoint SingleRactorMode
96619663
PatchPoint StableConstantNames(0x1000, O)
9662-
v15:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
9664+
v15:HeapObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
96639665
PatchPoint MethodRedefined(C@0x1010, foo@0x1018, cme:0x1020)
9664-
v18:HeapObject[VALUE(0x1008)] = GuardType v15, HeapObject
9665-
v19:HeapObject[VALUE(0x1008)] = GuardShape v18, 0x1048
9666+
v19:HeapObject[VALUE(0x1008)] = GuardShape v15, 0x1048
96669667
v20:NilClass = Const Value(nil)
96679668
CheckInterrupts
96689669
Return v20

zjit/src/hir_type/gen_hir_type.rb

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,50 +58,65 @@ def to_graphviz type
5858
$subclass = [basic_object_subclass.name, object_subclass.name]
5959
$builtin_exact = [basic_object_exact.name, object_exact.name]
6060

61+
$c_names = {
62+
"ObjectExact" => "rb_cObject",
63+
"BasicObjectExact" => "rb_cBasicObject",
64+
}
65+
6166
# Define a new type that can be subclassed (most of them).
62-
def base_type name
67+
# If c_name is given, mark the rb_cXYZ object as equivalent to this exact type.
68+
def base_type name, c_name: nil
6369
type = $object.subtype name
6470
exact = type.subtype(name+"Exact")
71+
if c_name
72+
$c_names[exact.name] = c_name
73+
end
6574
subclass = type.subtype(name+"Subclass")
6675
$builtin_exact << exact.name
6776
$subclass << subclass.name
6877
[type, exact]
6978
end
7079

7180
# Define a new type that cannot be subclassed.
72-
def final_type name
73-
type = $object.subtype name
81+
# If c_name is given, mark the rb_cXYZ object as equivalent to this type.
82+
def final_type name, base: $object, c_name: nil
83+
if c_name
84+
$c_names[name] = c_name
85+
end
86+
type = base.subtype name
7487
$builtin_exact << type.name
7588
type
7689
end
7790

78-
base_type "String"
79-
base_type "Array"
80-
base_type "Hash"
81-
base_type "Range"
82-
base_type "Set"
83-
base_type "Regexp"
84-
module_class, _ = base_type "Module"
85-
module_class.subtype "Class"
91+
base_type "String", c_name: "rb_cString"
92+
base_type "Array", c_name: "rb_cArray"
93+
base_type "Hash", c_name: "rb_cHash"
94+
base_type "Range", c_name: "rb_cRange"
95+
base_type "Set", c_name: "rb_cSet"
96+
base_type "Regexp", c_name: "rb_cRegexp"
97+
module_class, _ = base_type "Module", c_name: "rb_cModule"
98+
class_ = final_type "Class", base: module_class, c_name: "rb_cClass"
99+
100+
numeric, _ = base_type "Numeric", c_name: "rb_cNumeric"
86101

87-
integer_exact = final_type "Integer"
102+
integer_exact = final_type "Integer", base: numeric, c_name: "rb_cInteger"
88103
# CRuby partitions Integer into immediate and non-immediate variants.
89104
fixnum = integer_exact.subtype "Fixnum"
90105
integer_exact.subtype "Bignum"
91106

92-
float_exact = final_type "Float"
107+
float_exact = final_type "Float", base: numeric, c_name: "rb_cFloat"
93108
# CRuby partitions Float into immediate and non-immediate variants.
94109
flonum = float_exact.subtype "Flonum"
95110
float_exact.subtype "HeapFloat"
96111

97-
symbol_exact = final_type "Symbol"
112+
symbol_exact = final_type "Symbol", c_name: "rb_cSymbol"
98113
# CRuby partitions Symbol into immediate and non-immediate variants.
99114
static_sym = symbol_exact.subtype "StaticSymbol"
100115
symbol_exact.subtype "DynamicSymbol"
101116

102-
nil_exact = final_type "NilClass"
103-
true_exact = final_type "TrueClass"
104-
false_exact = final_type "FalseClass"
117+
nil_exact = final_type "NilClass", c_name: "rb_cNilClass"
118+
true_exact = final_type "TrueClass", c_name: "rb_cTrueClass"
119+
false_exact = final_type "FalseClass", c_name: "rb_cFalseClass"
105120

106121
# Build the cvalue object universe. This is for C-level types that may be
107122
# passed around when calling into the Ruby VM or after some strength reduction
@@ -183,4 +198,9 @@ def add_union name, type_names
183198
$bits.keys.sort.map {|type_name|
184199
puts " pub const #{type_name}: Type = Type::from_bits(bits::#{type_name});"
185200
}
201+
puts " pub const ExactBitsAndClass: [(u64, *const VALUE); #{$c_names.size}] = ["
202+
$c_names.each {|type_name, c_name|
203+
puts " (bits::#{type_name}, &raw const crate::cruby::#{c_name}),"
204+
}
205+
puts " ];"
186206
puts "}"

zjit/src/hir_type/hir_type.inc.rs

Lines changed: 46 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)