diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index 5faa1bbcc3..d4ed6304cb 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -449,8 +449,6 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio Insn::LoadPC => gen_load_pc(asm), Insn::LoadSelf => gen_load_self(), &Insn::LoadField { recv, id, offset, return_type: _ } => gen_load_field(asm, opnd!(recv), id, offset), - &Insn::LoadIvarEmbedded { self_val, id, index } => gen_load_ivar_embedded(asm, opnd!(self_val), id, index), - &Insn::LoadIvarExtended { self_val, id, index } => gen_load_ivar_extended(asm, opnd!(self_val), id, index), &Insn::IsBlockGiven => gen_is_block_given(jit, asm), &Insn::ArrayMax { state, .. } | &Insn::FixnumDiv { state, .. } @@ -988,29 +986,6 @@ fn gen_load_field(asm: &mut Assembler, recv: Opnd, id: ID, offset: i32) -> Opnd asm.load(Opnd::mem(64, recv, offset)) } -fn gen_load_ivar_embedded(asm: &mut Assembler, self_val: Opnd, id: ID, index: u16) -> Opnd { - // See ROBJECT_FIELDS() from include/ruby/internal/core/robject.h - - asm_comment!(asm, "Load embedded ivar id={} index={}", id.contents_lossy(), index); - let offs = ROBJECT_OFFSET_AS_ARY as i32 + (SIZEOF_VALUE * index.to_usize()) as i32; - let self_val = asm.load(self_val); - let ivar_opnd = Opnd::mem(64, self_val, offs); - asm.load(ivar_opnd) -} - -fn gen_load_ivar_extended(asm: &mut Assembler, self_val: Opnd, id: ID, index: u16) -> Opnd { - asm_comment!(asm, "Load extended ivar id={} index={}", id.contents_lossy(), index); - // Compile time value is *not* embedded. - - // Get a pointer to the extended table - let self_val = asm.load(self_val); - let tbl_opnd = asm.load(Opnd::mem(64, self_val, ROBJECT_OFFSET_AS_HEAP_FIELDS as i32)); - - // Read the ivar from the extended table - let ivar_opnd = Opnd::mem(64, tbl_opnd, (SIZEOF_VALUE * index.to_usize()) as i32); - asm.load(ivar_opnd) -} - /// Compile an interpreter entry block to be inserted into an ISEQ fn gen_entry_prologue(asm: &mut Assembler, iseq: IseqPtr) { asm_comment!(asm, "ZJIT entry point: {}", iseq_get_location(iseq, 0)); diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index 269336fb16..94becee9c8 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -676,10 +676,6 @@ pub enum Insn { /// Load cfp->self LoadSelf, LoadField { recv: InsnId, id: ID, offset: i32, return_type: Type }, - /// Read an instance variable at the given index, embedded in the object - LoadIvarEmbedded { self_val: InsnId, id: ID, index: u16 }, - /// Read an instance variable at the given index, from the extended table - LoadIvarExtended { self_val: InsnId, id: ID, index: u16 }, /// Get a local variable from a higher scope or the heap. /// If `use_sp` is true, it uses the SP register to optimize the read. @@ -915,8 +911,6 @@ impl Insn { Insn::LoadPC => false, Insn::LoadSelf => false, Insn::LoadField { .. } => false, - Insn::LoadIvarEmbedded { .. } => false, - Insn::LoadIvarExtended { .. } => false, Insn::CCall { elidable, .. } => !elidable, Insn::CCallWithFrame { elidable, .. } => !elidable, Insn::ObjectAllocClass { .. } => false, @@ -1177,8 +1171,6 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> { Insn::LoadPC => write!(f, "LoadPC"), Insn::LoadSelf => write!(f, "LoadSelf"), &Insn::LoadField { recv, id, offset, return_type: _ } => write!(f, "LoadField {recv}, :{}@{:p}", id.contents_lossy(), self.ptr_map.map_offset(offset)), - &Insn::LoadIvarEmbedded { self_val, id, index } => write!(f, "LoadIvarEmbedded {self_val}, :{}@{:p}", id.contents_lossy(), self.ptr_map.map_index(index as u64)), - &Insn::LoadIvarExtended { self_val, id, index } => write!(f, "LoadIvarExtended {self_val}, :{}@{:p}", id.contents_lossy(), self.ptr_map.map_index(index as u64)), Insn::SetIvar { self_val, id, val, .. } => write!(f, "SetIvar {self_val}, :{}, {val}", id.contents_lossy()), Insn::GetGlobal { id, .. } => write!(f, "GetGlobal :{}", id.contents_lossy()), Insn::SetGlobal { id, val, .. } => write!(f, "SetGlobal :{}, {val}", id.contents_lossy()), @@ -1800,8 +1792,6 @@ impl Function { &SetGlobal { id, val, state } => SetGlobal { id, val: find!(val), state }, &GetIvar { self_val, id, state } => GetIvar { self_val: find!(self_val), id, state }, &LoadField { recv, id, offset, return_type } => LoadField { recv: find!(recv), id, offset, return_type }, - &LoadIvarEmbedded { self_val, id, index } => LoadIvarEmbedded { self_val: find!(self_val), id, index }, - &LoadIvarExtended { self_val, id, index } => LoadIvarExtended { self_val: find!(self_val), id, index }, &SetIvar { self_val, id, val, state } => SetIvar { self_val: find!(self_val), id, val: find!(val), state }, &GetClassVar { id, ic, state } => GetClassVar { id, ic, state }, &SetClassVar { id, val, ic, state } => SetClassVar { id, val: find!(val), ic, state }, @@ -1938,8 +1928,6 @@ impl Function { Insn::LoadPC => types::CPtr, Insn::LoadSelf => types::BasicObject, &Insn::LoadField { return_type, .. } => return_type, - Insn::LoadIvarEmbedded { .. } => types::BasicObject, - Insn::LoadIvarExtended { .. } => types::BasicObject, Insn::GetSpecialSymbol { .. } => types::BasicObject, Insn::GetSpecialNumber { .. } => types::BasicObject, Insn::GetClassVar { .. } => types::BasicObject, @@ -2678,13 +2666,17 @@ impl Function { // If there is no IVAR index, then the ivar was undefined when we // entered the compiler. That means we can just return nil for this // shape + iv name - Insn::Const { val: Const::Value(Qnil) } + self.push_insn(block, Insn::Const { val: Const::Value(Qnil) }) } else if recv_type.flags().is_embedded() { - Insn::LoadIvarEmbedded { self_val, id, index: ivar_index } + // See ROBJECT_FIELDS() from include/ruby/internal/core/robject.h + let offset = ROBJECT_OFFSET_AS_ARY as i32 + (SIZEOF_VALUE * ivar_index.to_usize()) as i32; + self.push_insn(block, Insn::LoadField { recv: self_val, id, offset, return_type: types::BasicObject }) } else { - Insn::LoadIvarExtended { self_val, id, index: ivar_index } + let as_heap = self.push_insn(block, Insn::LoadField { recv: self_val, id: ID!(_as_heap), offset: ROBJECT_OFFSET_AS_HEAP_FIELDS as i32, return_type: types::CPtr }); + + let offset = SIZEOF_VALUE_I32 * ivar_index as i32; + self.push_insn(block, Insn::LoadField { recv: as_heap, id, offset, return_type: types::BasicObject }) }; - let replacement = self.push_insn(block, replacement); self.make_equal_to(insn_id, replacement); } _ => { self.push_insn_id(block, insn_id); } @@ -3376,10 +3368,6 @@ impl Function { &Insn::LoadField { recv, .. } => { worklist.push_back(recv); } - &Insn::LoadIvarEmbedded { self_val, .. } - | &Insn::LoadIvarExtended { self_val, .. } => { - worklist.push_back(self_val); - } &Insn::GuardBlockParamProxy { state, .. } | &Insn::GetGlobal { state, .. } | &Insn::GetSpecialSymbol { state, .. } | @@ -3754,8 +3742,6 @@ impl Function { self.assert_subtype(insn_id, val, types::BasicObject) } Insn::DefinedIvar { self_val, .. } => self.assert_subtype(insn_id, self_val, types::BasicObject), - Insn::LoadIvarEmbedded { self_val, .. } => self.assert_subtype(insn_id, self_val, types::HeapBasicObject), - Insn::LoadIvarExtended { self_val, .. } => self.assert_subtype(insn_id, self_val, types::HeapBasicObject), Insn::SetLocal { val, .. } => self.assert_subtype(insn_id, val, types::BasicObject), Insn::SetClassVar { val, .. } => self.assert_subtype(insn_id, val, types::BasicObject), Insn::IfTrue { val, .. } | Insn::IfFalse { val, .. } => self.assert_subtype(insn_id, val, types::CBool), diff --git a/zjit/src/hir/opt_tests.rs b/zjit/src/hir/opt_tests.rs index fd93b4a444..5247122023 100644 --- a/zjit/src/hir/opt_tests.rs +++ b/zjit/src/hir/opt_tests.rs @@ -4551,7 +4551,7 @@ mod hir_opt_tests { PatchPoint NoSingletonClass(C@0x1000) v22:HeapObject[class_exact:C] = GuardType v9, HeapObject[class_exact:C] v25:HeapObject[class_exact:C] = GuardShape v22, 0x1038 - v26:BasicObject = LoadIvarEmbedded v25, :@foo@0x1039 + v26:BasicObject = LoadField v25, :@foo@0x1039 CheckInterrupts Return v26 "); @@ -4590,9 +4590,10 @@ mod hir_opt_tests { PatchPoint NoSingletonClass(C@0x1000) v22:HeapObject[class_exact:C] = GuardType v9, HeapObject[class_exact:C] v25:HeapObject[class_exact:C] = GuardShape v22, 0x1038 - v26:BasicObject = LoadIvarExtended v25, :@foo@0x1039 + v26:CPtr = LoadField v25, :_as_heap@0x1039 + v27:BasicObject = LoadField v26, :@foo@0x103a CheckInterrupts - Return v26 + Return v27 "); }