Skip to content

Commit 9e65f0c

Browse files
committed
ZJIT: Profiling: Separate bits for T_CLASS and T_MODULE
So I don't need to use is_subclass_of(). We already have two branches for the two types during profiling anyways.
1 parent 78d9486 commit 9e65f0c

File tree

2 files changed

+24
-12
lines changed

2 files changed

+24
-12
lines changed

zjit/src/hir.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4422,10 +4422,10 @@ impl Function {
44224422

44234423
/// This puts a guard that establishes the preconditon for [Self::load_ivar]
44244424
fn load_ivar_guard_type(&mut self, block: BlockId, recv: InsnId, recv_type: ProfiledType, state: InsnId) -> InsnId {
4425-
if recv_type.class().is_subclass_of(unsafe { rb_cClass }) == ClassRelationship::Subclass {
4425+
if recv_type.flags().is_t_class() {
44264426
// Check class first since `Class < Module`
44274427
self.push_insn(block, Insn::GuardType { val: recv, guard_type: types::Class, state })
4428-
} else if recv_type.class().is_subclass_of(unsafe { rb_cModule }) == ClassRelationship::Subclass {
4428+
} else if recv_type.flags().is_t_module() {
44294429
self.push_insn(block, Insn::GuardType { val: recv, guard_type: types::Module, state })
44304430
} else if recv_type.flags().is_typed_data() {
44314431
self.push_insn(block, Insn::GuardType { val: recv, guard_type: types::TypedTData, state })
@@ -4448,7 +4448,7 @@ impl Function {
44484448
// shape + iv name
44494449
return self.push_insn(block, Insn::Const { val: Const::Value(Qnil) });
44504450
}
4451-
if recv_type.flags().is_t_class_or_module() {
4451+
if recv_type.flags().is_t_class() || recv_type.flags().is_t_module() {
44524452
// Class/module ivar: load from prime classext's fields_obj
44534453
if !self.assume_root_box(block, state) {
44544454
// Non-root box active: fall back to C call

zjit/src/profile.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,12 @@ impl Flags {
206206
const IS_OBJECT_PROFILING: u32 = 1 << 4;
207207
/// Class/module fields_obj is embedded (or absent)
208208
const IS_FIELDS_EMBEDDED: u32 = 1 << 5;
209-
/// Object is a T_CLASS or T_MODULE
210-
const IS_T_CLASS_OR_MODULE: u32 = 1 << 6;
209+
/// Object is a T_CLASS
210+
const IS_T_CLASS: u32 = 1 << 6;
211+
/// Object is a T_MODULE
212+
const IS_T_MODULE: u32 = 1 << 7;
211213
/// Object is a typed T_DATA (RTYPEDDATA_P)
212-
const IS_TYPED_DATA: u32 = 1 << 7;
214+
const IS_TYPED_DATA: u32 = 1 << 8;
213215

214216
pub fn none() -> Self { Self(Self::NONE) }
215217

@@ -220,7 +222,8 @@ impl Flags {
220222
pub fn is_struct_embedded(self) -> bool { (self.0 & Self::IS_STRUCT_EMBEDDED) != 0 }
221223
pub fn is_object_profiling(self) -> bool { (self.0 & Self::IS_OBJECT_PROFILING) != 0 }
222224
pub fn is_fields_embedded(self) -> bool { (self.0 & Self::IS_FIELDS_EMBEDDED) != 0 }
223-
pub fn is_t_class_or_module(self) -> bool { (self.0 & Self::IS_T_CLASS_OR_MODULE) != 0 }
225+
pub fn is_t_class(self) -> bool { (self.0 & Self::IS_T_CLASS) != 0 }
226+
pub fn is_t_module(self) -> bool { (self.0 & Self::IS_T_MODULE) != 0 }
224227
pub fn is_typed_data(self) -> bool { (self.0 & Self::IS_TYPED_DATA) != 0 }
225228
}
226229

@@ -298,8 +301,14 @@ impl ProfiledType {
298301
if unsafe { RB_TYPE_P(obj, RUBY_T_OBJECT) } {
299302
flags.0 |= Flags::IS_T_OBJECT;
300303
}
301-
if unsafe { RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE) } {
302-
flags.0 |= Flags::IS_T_CLASS_OR_MODULE;
304+
if unsafe { RB_TYPE_P(obj, RUBY_T_CLASS) } {
305+
flags.0 |= Flags::IS_T_CLASS;
306+
if obj.class_fields_embedded_p() {
307+
flags.0 |= Flags::IS_FIELDS_EMBEDDED;
308+
}
309+
}
310+
if unsafe { RB_TYPE_P(obj, RUBY_T_MODULE) } {
311+
flags.0 |= Flags::IS_T_MODULE;
303312
if obj.class_fields_embedded_p() {
304313
flags.0 |= Flags::IS_FIELDS_EMBEDDED;
305314
}
@@ -333,16 +342,19 @@ impl ProfiledType {
333342
self.flags
334343
}
335344

336-
/// For ivar access
345+
/// For ivar access, you need to know the index in the fields array (described by the shape)
346+
/// and the way to get the fields array (described by the builtin type). Both pieces of
347+
/// information are on the `RBasic::flags` field. This method returns expected masked flags
348+
/// for guarding.
337349
pub fn rbasic_flags_and_mask(&self) -> (u64, u64) {
338350
let shape_flag_shift = u64::from(RB_SHAPE_FLAG_SHIFT);
339351
let (shape, shape_mask) = (u64::from(self.shape().0) << shape_flag_shift, !0 << shape_flag_shift);
340352
let (builtin_type, type_mask) = if self.flags().is_t_object() {
341353
(RUBY_T_OBJECT, RUBY_T_MASK)
342-
} else if self.class().is_subclass_of(unsafe { rb_cClass }) == ClassRelationship::Subclass {
354+
} else if self.flags().is_t_class() {
343355
// Check class first since `Class < Module`
344356
(RUBY_T_CLASS, RUBY_T_MASK)
345-
} else if self.class().is_subclass_of(unsafe { rb_cModule }) == ClassRelationship::Subclass {
357+
} else if self.flags().is_t_module() {
346358
(RUBY_T_MODULE, RUBY_T_MASK)
347359
} else if self.flags().is_typed_data() {
348360
(RUBY_T_DATA | RUBY_TYPED_FL_IS_TYPED_DATA, RUBY_T_MASK | RUBY_TYPED_FL_IS_TYPED_DATA)

0 commit comments

Comments
 (0)