Skip to content

Commit 7a074db

Browse files
committed
Support inference of ClassExact type
1 parent 7349a1a commit 7a074db

4 files changed

Lines changed: 123 additions & 40 deletions

File tree

zjit/src/hir.rs

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4051,10 +4051,10 @@ mod tests {
40514051
assert_method_hir("test", expect![[r#"
40524052
fn test:
40534053
bb0(v0:BasicObject, v1:BasicObject):
4054-
v3:BasicObject[VMFrozenCore] = Const Value(VALUE(0x1000))
4054+
v3:ClassExact[VMFrozenCore] = Const Value(VALUE(0x1000))
40554055
v5:HashExact = NewHash
40564056
v7:BasicObject = SendWithoutBlock v3, :core#hash_merge_kwd, v5, v1
4057-
v8:BasicObject[VMFrozenCore] = Const Value(VALUE(0x1000))
4057+
v8:ClassExact[VMFrozenCore] = Const Value(VALUE(0x1000))
40584058
v9:StaticSymbol[:b] = Const Value(VALUE(0x1008))
40594059
v10:Fixnum[1] = Const Value(1)
40604060
v12:BasicObject = SendWithoutBlock v8, :core#hash_merge_ptr, v7, v9, v10
@@ -4503,7 +4503,7 @@ mod tests {
45034503
assert_method_hir_with_opcode("test", YARVINSN_putspecialobject, expect![[r#"
45044504
fn test:
45054505
bb0(v0:BasicObject):
4506-
v2:BasicObject[VMFrozenCore] = Const Value(VALUE(0x1000))
4506+
v2:ClassExact[VMFrozenCore] = Const Value(VALUE(0x1000))
45074507
v3:BasicObject = PutSpecialObject CBase
45084508
v4:StaticSymbol[:aliased] = Const Value(VALUE(0x1008))
45094509
v5:StaticSymbol[:__callee__] = Const Value(VALUE(0x1010))
@@ -5731,6 +5731,69 @@ mod opt_tests {
57315731
"#]]);
57325732
}
57335733

5734+
#[test]
5735+
fn normal_class_type_inference() {
5736+
eval("
5737+
class C; end
5738+
def test = C
5739+
test # Warm the constant cache
5740+
");
5741+
assert_optimized_method_hir("test", expect![[r#"
5742+
fn test:
5743+
bb0(v0:BasicObject):
5744+
PatchPoint SingleRactorMode
5745+
PatchPoint StableConstantNames(0x1000, C)
5746+
v7:ClassExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5747+
Return v7
5748+
"#]]);
5749+
}
5750+
5751+
#[test]
5752+
fn core_classes_type_inference() {
5753+
eval("
5754+
def test = [String, Class, Module, BasicObject]
5755+
test # Warm the constant cache
5756+
");
5757+
assert_optimized_method_hir("test", expect![[r#"
5758+
fn test:
5759+
bb0(v0:BasicObject):
5760+
PatchPoint SingleRactorMode
5761+
PatchPoint StableConstantNames(0x1000, String)
5762+
v15:ClassExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5763+
PatchPoint SingleRactorMode
5764+
PatchPoint StableConstantNames(0x1010, Class)
5765+
v18:ClassExact[VALUE(0x1018)] = Const Value(VALUE(0x1018))
5766+
PatchPoint SingleRactorMode
5767+
PatchPoint StableConstantNames(0x1020, Module)
5768+
v21:ClassExact[VALUE(0x1028)] = Const Value(VALUE(0x1028))
5769+
PatchPoint SingleRactorMode
5770+
PatchPoint StableConstantNames(0x1030, BasicObject)
5771+
v24:ClassExact[VALUE(0x1038)] = Const Value(VALUE(0x1038))
5772+
v11:ArrayExact = NewArray v15, v18, v21, v24
5773+
Return v11
5774+
"#]]);
5775+
}
5776+
5777+
#[test]
5778+
fn module_instances_not_class_exact() {
5779+
eval("
5780+
def test = [Enumerable, Kernel]
5781+
test # Warm the constant cache
5782+
");
5783+
assert_optimized_method_hir("test", expect![[r#"
5784+
fn test:
5785+
bb0(v0:BasicObject):
5786+
PatchPoint SingleRactorMode
5787+
PatchPoint StableConstantNames(0x1000, Enumerable)
5788+
v11:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5789+
PatchPoint SingleRactorMode
5790+
PatchPoint StableConstantNames(0x1010, Kernel)
5791+
v14:BasicObject[VALUE(0x1018)] = Const Value(VALUE(0x1018))
5792+
v7:ArrayExact = NewArray v11, v14
5793+
Return v7
5794+
"#]]);
5795+
}
5796+
57345797
#[test]
57355798
fn eliminate_array_size() {
57365799
eval("
@@ -5880,7 +5943,7 @@ mod opt_tests {
58805943
bb0(v0:BasicObject):
58815944
PatchPoint SingleRactorMode
58825945
PatchPoint StableConstantNames(0x1000, Foo::Bar::C)
5883-
v7:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5946+
v7:ClassExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
58845947
Return v7
58855948
"#]]);
58865949
}
@@ -5897,7 +5960,7 @@ mod opt_tests {
58975960
bb0(v0:BasicObject):
58985961
PatchPoint SingleRactorMode
58995962
PatchPoint StableConstantNames(0x1000, C)
5900-
v20:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5963+
v20:ClassExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
59015964
v4:NilClassExact = Const Value(nil)
59025965
v11:BasicObject = SendWithoutBlock v20, :new
59035966
Return v11
@@ -5920,7 +5983,7 @@ mod opt_tests {
59205983
bb0(v0:BasicObject):
59215984
PatchPoint SingleRactorMode
59225985
PatchPoint StableConstantNames(0x1000, C)
5923-
v22:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5986+
v22:ClassExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
59245987
v4:NilClassExact = Const Value(nil)
59255988
v5:Fixnum[1] = Const Value(1)
59265989
v13:BasicObject = SendWithoutBlock v22, :new, v5

zjit/src/hir_type/gen_hir_type.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ def base_type name
7474
base_type "Range"
7575
base_type "Set"
7676
base_type "Regexp"
77+
base_type "Class"
7778

7879
(integer, integer_exact) = base_type "Integer"
7980
# CRuby partitions Integer into immediate and non-immediate variants.

zjit/src/hir_type/hir_type.inc.rs

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

zjit/src/hir_type/mod.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![allow(non_upper_case_globals)]
2-
use crate::cruby::{Qfalse, Qnil, Qtrue, VALUE, RUBY_T_ARRAY, RUBY_T_STRING, RUBY_T_HASH};
3-
use crate::cruby::{rb_cInteger, rb_cFloat, rb_cArray, rb_cHash, rb_cString, rb_cSymbol, rb_cObject, rb_cTrueClass, rb_cFalseClass, rb_cNilClass, rb_cRange, rb_cSet, rb_cRegexp};
2+
use crate::cruby::{Qfalse, Qnil, Qtrue, VALUE, RUBY_T_ARRAY, RUBY_T_STRING, RUBY_T_HASH, RUBY_T_CLASS};
3+
use crate::cruby::{rb_cInteger, rb_cFloat, rb_cArray, rb_cHash, rb_cString, rb_cSymbol, rb_cObject, rb_cTrueClass, rb_cFalseClass, rb_cNilClass, rb_cRange, rb_cSet, rb_cRegexp, rb_cClass, rb_cModule};
44
use crate::cruby::ClassRelationship;
55
use crate::cruby::get_class_name;
66
use crate::cruby::ruby_sym_to_rust_string;
@@ -145,6 +145,11 @@ fn is_range_exact(val: VALUE) -> bool {
145145
val.class_of() == unsafe { rb_cRange }
146146
}
147147

148+
fn is_class_exact(val: VALUE) -> bool {
149+
// Objects with RUBY_T_CLASS type and not instances of Module
150+
val.builtin_type() == RUBY_T_CLASS && val.class_of() != unsafe { rb_cModule }
151+
}
152+
148153
impl Type {
149154
/// Create a `Type` from the given integer.
150155
pub const fn fixnum(val: i64) -> Type {
@@ -197,6 +202,9 @@ impl Type {
197202
else if is_string_exact(val) {
198203
Type { bits: bits::StringExact, spec: Specialization::Object(val) }
199204
}
205+
else if is_class_exact(val) {
206+
Type { bits: bits::ClassExact, spec: Specialization::Object(val) }
207+
}
200208
else if val.class_of() == unsafe { rb_cRegexp } {
201209
Type { bits: bits::RegexpExact, spec: Specialization::Object(val) }
202210
}
@@ -288,6 +296,7 @@ impl Type {
288296

289297
fn is_builtin(class: VALUE) -> bool {
290298
if class == unsafe { rb_cArray } { return true; }
299+
if class == unsafe { rb_cClass } { return true; }
291300
if class == unsafe { rb_cFalseClass } { return true; }
292301
if class == unsafe { rb_cFloat } { return true; }
293302
if class == unsafe { rb_cHash } { return true; }
@@ -396,6 +405,7 @@ impl Type {
396405
return Some(val);
397406
}
398407
if self.is_subtype(types::ArrayExact) { return Some(unsafe { rb_cArray }); }
408+
if self.is_subtype(types::ClassExact) { return Some(unsafe { rb_cClass }); }
399409
if self.is_subtype(types::FalseClassExact) { return Some(unsafe { rb_cFalseClass }); }
400410
if self.is_subtype(types::FloatExact) { return Some(unsafe { rb_cFloat }); }
401411
if self.is_subtype(types::HashExact) { return Some(unsafe { rb_cHash }); }

0 commit comments

Comments
 (0)