Skip to content

Commit 4cfb893

Browse files
committed
ZJIT: ivar code cleanup
I just wanted to clean up some of the IV handling code in ZJIT. If classes, modules, or TDATA have instance variables, and they aren't "too complex", the instance variables will always be in an external buffer. Since we can make these assertions at compile time, it allows us to clean up some of this code
1 parent 0df3614 commit 4cfb893

6 files changed

Lines changed: 9 additions & 86 deletions

File tree

jit.c

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -560,20 +560,6 @@ rb_jit_multi_ractor_p(void)
560560
return rb_multi_ractor_p();
561561
}
562562

563-
bool
564-
rb_jit_class_fields_embedded_p(VALUE klass)
565-
{
566-
VALUE fields_obj = RCLASS_EXT_PRIME(klass)->fields_obj;
567-
return !fields_obj || !FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP);
568-
}
569-
570-
bool
571-
rb_jit_data_fields_embedded_p(VALUE obj)
572-
{
573-
VALUE fields_obj = RTYPEDDATA(obj)->fields_obj;
574-
return !fields_obj || !FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP);
575-
}
576-
577563
// Acquire the VM lock and then signal all other Ruby threads (ractors) to
578564
// contend for the VM lock, putting them to sleep. ZJIT and YJIT use this to
579565
// evict threads running inside generated code so among other things, it can

zjit/bindgen/src/main.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,6 @@ fn main() {
319319
.allowlist_function("rb_assert_holding_vm_lock")
320320
.allowlist_function("rb_jit_shape_complex_p")
321321
.allowlist_function("rb_jit_multi_ractor_p")
322-
.allowlist_function("rb_jit_class_fields_embedded_p")
323-
.allowlist_function("rb_jit_data_fields_embedded_p")
324322
.allowlist_function("rb_jit_vm_lock_then_barrier")
325323
.allowlist_function("rb_jit_vm_unlock")
326324
.allowlist_function("rb_jit_for_each_iseq")

zjit/src/cruby.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -629,19 +629,11 @@ impl VALUE {
629629
}
630630
}
631631

632-
pub fn class_fields_embedded_p(self) -> bool {
633-
unsafe { rb_jit_class_fields_embedded_p(self) }
634-
}
635-
636632
pub fn data_p(self) -> bool {
637633
!self.special_const_p() &&
638634
self.builtin_type() == RUBY_T_DATA
639635
}
640636

641-
pub fn data_fields_embedded_p(self) -> bool {
642-
unsafe { rb_jit_data_fields_embedded_p(self) }
643-
}
644-
645637
pub fn as_fixnum(self) -> i64 {
646638
assert!(self.fixnum_p());
647639
(self.0 as i64) >> 1

zjit/src/cruby_bindings.inc.rs

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

zjit/src/hir.rs

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4373,31 +4373,6 @@ impl Function {
43734373
})
43744374
}
43754375

4376-
fn load_ivar_from_fields(&mut self, block: BlockId, recv: InsnId, is_embedded: bool, id: ID, ivar_index: attr_index_t) -> InsnId {
4377-
if is_embedded {
4378-
return self.load_ivar_embedded(block, recv, id, ivar_index);
4379-
} else {
4380-
return self.load_ivar_heap(block, recv, id, ivar_index);
4381-
}
4382-
}
4383-
4384-
/// This puts a guard that establishes the preconditon for [Self::load_ivar]
4385-
fn load_ivar_guard_type(&mut self, block: BlockId, recv: InsnId, recv_type: ProfiledType, state: InsnId) -> InsnId {
4386-
if recv_type.flags().is_t_class() {
4387-
// Check class first since `Class < Module`
4388-
self.push_insn(block, Insn::GuardType { val: recv, guard_type: types::Class, state, recompile: None })
4389-
} else if recv_type.flags().is_t_module() {
4390-
self.push_insn(block, Insn::GuardType { val: recv, guard_type: types::Module, state, recompile: None })
4391-
} else if recv_type.flags().is_t_data() {
4392-
self.push_insn(block, Insn::GuardType { val: recv, guard_type: types::TData, state, recompile: None })
4393-
} else {
4394-
// HeapBasicObject is wider than T_OBJECT, but shapes for T_OBJECTs are in a pool of
4395-
// its own and are guaranteed to be different from shapes of any other T_* types. So
4396-
// the shape check that follows already covers checking for T_OBJECT.
4397-
self.push_insn(block, Insn::GuardType { val: recv, guard_type: types::HeapBasicObject, state, recompile: None })
4398-
}
4399-
}
4400-
44014376
fn load_ivar(&mut self, block: BlockId, self_val: InsnId, recv_type: ProfiledType, id: ID) -> InsnId {
44024377
// Too-complex shapes use hash tables; rb_shape_get_iv_index doesn't support them.
44034378
// Callers must filter these out before calling load_ivar.
@@ -4425,10 +4400,14 @@ impl Function {
44254400
offset,
44264401
return_type: types::RubyValue,
44274402
});
4428-
self.load_ivar_from_fields(block, fields_obj, recv_type.flags().is_fields_embedded(), id, ivar_index)
4403+
self.load_ivar_embedded(block, fields_obj, id, ivar_index)
44294404
},
44304405
ShapeLayout::RObject => {
4431-
self.load_ivar_from_fields(block, self_val, recv_type.flags().is_embedded(), id, ivar_index)
4406+
if recv_type.flags().is_embedded() {
4407+
self.load_ivar_embedded(block, self_val, id, ivar_index)
4408+
} else {
4409+
self.load_ivar_heap(block, self_val, id, ivar_index)
4410+
}
44324411
},
44334412
ShapeLayout::Other => {
44344413
// Non-T_OBJECT, non-class/module, non-typed-data: fall back to C call
@@ -4470,7 +4449,7 @@ impl Function {
44704449
// need to wrap it again here.
44714450
self.push_insn_id(block, insn_id); continue;
44724451
}
4473-
let self_val = self.load_ivar_guard_type(block, self_val, recv_type, state);
4452+
let self_val = self.push_insn(block, Insn::GuardType { val: self_val, guard_type: types::HeapBasicObject, state, recompile: None });
44744453
let shape = self.load_shape(block, self_val);
44754454
self.guard_shape(block, shape, recv_type.shape(), state, Some(Recompile::ProfileSelf));
44764455
let replacement = self.load_ivar(block, self_val, recv_type, id);
@@ -4503,7 +4482,7 @@ impl Function {
45034482
// On the final version, keep the DefinedIvar fallback instead of another shape guard.
45044483
self.push_insn_id(block, insn_id); continue;
45054484
}
4506-
let self_val = self.load_ivar_guard_type(block, self_val, recv_type, state);
4485+
let self_val = self.push_insn(block, Insn::GuardType { val: self_val, guard_type: types::HeapBasicObject, state, recompile: None });
45074486
let shape = self.load_shape(block, self_val);
45084487
self.guard_shape(block, shape, recv_type.shape(), state, Some(Recompile::ProfileSelf));
45094488
let mut ivar_index: attr_index_t = 0;
@@ -4581,7 +4560,7 @@ impl Function {
45814560
}
45824561
// Fall through to emitting the ivar write
45834562
}
4584-
let self_val = self.load_ivar_guard_type(block, self_val, recv_type, state);
4563+
let self_val = self.push_insn(block, Insn::GuardType { val: self_val, guard_type: types::HeapBasicObject, state, recompile: None });
45854564
let shape = self.load_shape(block, self_val);
45864565
// TODO: attr_writer SetIvar has a null inline cache and may target a receiver
45874566
// operand other than CFP self. Support it with a reprofile strategy that

zjit/src/profile.rs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -213,14 +213,6 @@ impl Flags {
213213
const IS_STRUCT_EMBEDDED: u32 = 1 << 3;
214214
/// Set if the ProfiledType is used for profiling specific objects, not just classes/shapes
215215
const IS_OBJECT_PROFILING: u32 = 1 << 4;
216-
/// Class/module fields_obj is embedded (or absent)
217-
const IS_FIELDS_EMBEDDED: u32 = 1 << 5;
218-
/// Object is a T_CLASS
219-
const IS_T_CLASS: u32 = 1 << 6;
220-
/// Object is a T_MODULE
221-
const IS_T_MODULE: u32 = 1 << 7;
222-
/// Object is a T_DATA
223-
const IS_T_DATA: u32 = 1 << 8;
224216

225217
pub fn none() -> Self { Self(Self::NONE) }
226218

@@ -230,10 +222,6 @@ impl Flags {
230222
pub fn is_t_object(self) -> bool { (self.0 & Self::IS_T_OBJECT) != 0 }
231223
pub fn is_struct_embedded(self) -> bool { (self.0 & Self::IS_STRUCT_EMBEDDED) != 0 }
232224
pub fn is_object_profiling(self) -> bool { (self.0 & Self::IS_OBJECT_PROFILING) != 0 }
233-
pub fn is_fields_embedded(self) -> bool { (self.0 & Self::IS_FIELDS_EMBEDDED) != 0 }
234-
pub fn is_t_class(self) -> bool { (self.0 & Self::IS_T_CLASS) != 0 }
235-
pub fn is_t_module(self) -> bool { (self.0 & Self::IS_T_MODULE) != 0 }
236-
pub fn is_t_data(self) -> bool { (self.0 & Self::IS_T_DATA) != 0 }
237225
}
238226

239227
/// opt_send_without_block/opt_plus/... should store:
@@ -310,24 +298,6 @@ impl ProfiledType {
310298
if unsafe { RB_TYPE_P(obj, RUBY_T_OBJECT) } {
311299
flags.0 |= Flags::IS_T_OBJECT;
312300
}
313-
if unsafe { RB_TYPE_P(obj, RUBY_T_CLASS) } {
314-
flags.0 |= Flags::IS_T_CLASS;
315-
if obj.class_fields_embedded_p() {
316-
flags.0 |= Flags::IS_FIELDS_EMBEDDED;
317-
}
318-
}
319-
if unsafe { RB_TYPE_P(obj, RUBY_T_MODULE) } {
320-
flags.0 |= Flags::IS_T_MODULE;
321-
if obj.class_fields_embedded_p() {
322-
flags.0 |= Flags::IS_FIELDS_EMBEDDED;
323-
}
324-
}
325-
if obj.data_p() {
326-
flags.0 |= Flags::IS_T_DATA;
327-
if obj.data_fields_embedded_p() {
328-
flags.0 |= Flags::IS_FIELDS_EMBEDDED;
329-
}
330-
}
331301
Self { class: obj.class_of(), shape: obj.shape_id_of(), flags }
332302
}
333303

0 commit comments

Comments
 (0)