diff options
author | Alan Wu <[email protected]> | 2025-06-17 01:09:09 +0900 |
---|---|---|
committer | Alan Wu <[email protected]> | 2025-06-17 20:51:58 +0900 |
commit | 0933400f451813f08671dd02462f1a718e99d564 (patch) | |
tree | 1d2aa00f17856fad6e11e57261d50d4ae8108c87 /zjit/src | |
parent | 01ff17fa40cdfbd811ec3b0c13034936451e693a (diff) |
ZJIT: Add codegen (and FrameState) for GetConstPath
Issue a call to rb_vm_opt_getconstant_path() like the interpreter, but
since that allocates the IC, we need to save the PC before calling. Add
FrameState to GetConstPath to get access to the PC.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/13628
Diffstat (limited to 'zjit/src')
-rw-r--r-- | zjit/src/codegen.rs | 16 | ||||
-rw-r--r-- | zjit/src/hir.rs | 93 |
2 files changed, 65 insertions, 44 deletions
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index 286f3f39b4..b1869f71c0 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -278,6 +278,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio Insn::GetIvar { self_val, id, state: _ } => gen_getivar(asm, opnd!(self_val), *id), Insn::SetGlobal { id, val, state: _ } => gen_setglobal(asm, *id, opnd!(val)), Insn::GetGlobal { id, state: _ } => gen_getglobal(asm, *id), + Insn::GetConstantPath { ic, state } => gen_get_constant_path(asm, *ic, &function.frame_state(*state)), Insn::SetIvar { self_val, id, val, state: _ } => return gen_setivar(asm, opnd!(self_val), *id, opnd!(val)), Insn::SideExit { state } => return gen_side_exit(jit, asm, &function.frame_state(*state)), Insn::PutSpecialObject { value_type } => gen_putspecialobject(asm, *value_type), @@ -295,6 +296,21 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio Some(()) } +fn gen_get_constant_path(asm: &mut Assembler, ic: *const iseq_inline_constant_cache, state: &FrameState) -> Opnd { + unsafe extern "C" { + fn rb_vm_opt_getconstant_path(ec: EcPtr, cfp: CfpPtr, ic: *const iseq_inline_constant_cache) -> VALUE; + } + + // Save PC since the call can allocate an IC + gen_save_pc(asm, state); + + let val = asm.ccall( + rb_vm_opt_getconstant_path as *const u8, + vec![EC, CFP, Opnd::const_ptr(ic as *const u8)], + ); + val +} + /// Lowering for [`Insn::CCall`]. This is a low-level raw call that doesn't know /// anything about the callee, so handling for e.g. GC safety is dealt with elsewhere. fn gen_ccall(jit: &mut JITState, asm: &mut Assembler, cfun: *const u8, args: &[InsnId]) -> Option<lir::Opnd> { diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index 4ef210fb8a..fbca1f4418 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -431,7 +431,7 @@ pub enum Insn { /// Return C `true` if `val` is `Qnil`, else `false`. IsNil { val: InsnId }, Defined { op_type: usize, obj: VALUE, pushval: VALUE, v: InsnId }, - GetConstantPath { ic: *const iseq_inline_constant_cache }, + GetConstantPath { ic: *const iseq_inline_constant_cache, state: InsnId }, /// Get a global variable named `id` GetGlobal { id: ID, state: InsnId }, @@ -651,7 +651,7 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> { Insn::GuardType { val, guard_type, .. } => { write!(f, "GuardType {val}, {}", guard_type.print(self.ptr_map)) }, Insn::GuardBitEquals { val, expected, .. } => { write!(f, "GuardBitEquals {val}, {}", expected.print(self.ptr_map)) }, Insn::PatchPoint(invariant) => { write!(f, "PatchPoint {}", invariant.print(self.ptr_map)) }, - Insn::GetConstantPath { ic } => { write!(f, "GetConstantPath {:p}", self.ptr_map.map_ptr(ic)) }, + Insn::GetConstantPath { ic, .. } => { write!(f, "GetConstantPath {:p}", self.ptr_map.map_ptr(ic)) }, Insn::CCall { cfun, args, name, return_type: _, elidable: _ } => { write!(f, "CCall {}@{:p}", name.contents_lossy(), self.ptr_map.map_ptr(cfun))?; for arg in args { @@ -1355,7 +1355,7 @@ impl Function { let send_direct = self.push_insn(block, Insn::SendWithoutBlockDirect { self_val, call_info, cd, cme, iseq, args, state }); self.make_equal_to(insn_id, send_direct); } - Insn::GetConstantPath { ic } => { + Insn::GetConstantPath { ic, .. } => { let idlist: *const ID = unsafe { (*ic).segments }; let ice = unsafe { (*ic).entry }; if ice.is_null() { @@ -1642,10 +1642,14 @@ impl Function { if necessary[insn_id.0] { continue; } necessary[insn_id.0] = true; match self.find(insn_id) { - Insn::Const { .. } | Insn::Param { .. } - | Insn::PatchPoint(..) | Insn::GetConstantPath { .. } + Insn::Const { .. } + | Insn::Param { .. } + | Insn::PatchPoint(..) | Insn::PutSpecialObject { .. } => {} + Insn::GetConstantPath { ic: _, state } => { + worklist.push_back(state); + } Insn::ArrayMax { elements, state } | Insn::NewArray { elements, state } => { worklist.extend(elements); @@ -2309,7 +2313,8 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { } YARVINSN_opt_getconstant_path => { let ic = get_arg(pc, 0).as_ptr(); - state.stack_push(fun.push_insn(block, Insn::GetConstantPath { ic })); + let snapshot = fun.push_insn(block, Insn::Snapshot { state: exit_state }); + state.stack_push(fun.push_insn(block, Insn::GetConstantPath { ic, state: snapshot })); } YARVINSN_branchunless => { let offset = get_arg(pc, 0).as_i64(); @@ -3745,14 +3750,14 @@ mod tests { assert_method_hir_with_opcode("test", YARVINSN_opt_new, expect![[r#" fn test: bb0(v0:BasicObject): - v2:BasicObject = GetConstantPath 0x1000 - v3:NilClassExact = Const Value(nil) - Jump bb1(v0, v3, v2) - bb1(v5:BasicObject, v6:NilClassExact, v7:BasicObject): - v10:BasicObject = SendWithoutBlock v7, :new - Jump bb2(v5, v10, v6) - bb2(v12:BasicObject, v13:BasicObject, v14:NilClassExact): - Return v13 + v3:BasicObject = GetConstantPath 0x1000 + v4:NilClassExact = Const Value(nil) + Jump bb1(v0, v4, v3) + bb1(v6:BasicObject, v7:NilClassExact, v8:BasicObject): + v11:BasicObject = SendWithoutBlock v8, :new + Jump bb2(v6, v11, v7) + bb2(v13:BasicObject, v14:BasicObject, v15:NilClassExact): + Return v14 "#]]); } @@ -5155,9 +5160,9 @@ mod opt_tests { assert_optimized_method_hir("test", expect![[r#" fn test: bb0(v0:BasicObject): - v2:BasicObject = GetConstantPath 0x1000 - v3:Fixnum[5] = Const Value(5) - Return v3 + v3:BasicObject = GetConstantPath 0x1000 + v4:Fixnum[5] = Const Value(5) + Return v4 "#]]); } @@ -5226,8 +5231,8 @@ mod opt_tests { PatchPoint SingleRactorMode PatchPoint StableConstantNames(0x1000, M) PatchPoint MethodRedefined(Module@0x1008, name@0x1010) - v6:Fixnum[1] = Const Value(1) - Return v6 + v7:Fixnum[1] = Const Value(1) + Return v7 "#]]); } @@ -5344,8 +5349,8 @@ mod opt_tests { assert_optimized_method_hir("test", expect![[r#" fn test: bb0(v0:BasicObject): - v2:BasicObject = GetConstantPath 0x1000 - Return v2 + v3:BasicObject = GetConstantPath 0x1000 + Return v3 "#]]); } @@ -5359,8 +5364,8 @@ mod opt_tests { assert_optimized_method_hir("test", expect![[r#" fn test: bb0(v0:BasicObject): - v2:BasicObject = GetConstantPath 0x1000 - Return v2 + v3:BasicObject = GetConstantPath 0x1000 + Return v3 "#]]); } @@ -5375,8 +5380,8 @@ mod opt_tests { bb0(v0:BasicObject): PatchPoint SingleRactorMode PatchPoint StableConstantNames(0x1000, Kernel) - v6:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008)) - Return v6 + v7:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008)) + Return v7 "#]]); } @@ -5397,8 +5402,8 @@ mod opt_tests { bb0(v0:BasicObject): PatchPoint SingleRactorMode PatchPoint StableConstantNames(0x1000, Foo::Bar::C) - v6:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008)) - Return v6 + v7:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008)) + Return v7 "#]]); } @@ -5414,14 +5419,14 @@ mod opt_tests { bb0(v0:BasicObject): PatchPoint SingleRactorMode PatchPoint StableConstantNames(0x1000, C) - v19:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008)) - v3:NilClassExact = Const Value(nil) - Jump bb1(v0, v3, v19) - bb1(v5:BasicObject, v6:NilClassExact, v7:BasicObject[VALUE(0x1008)]): - v10:BasicObject = SendWithoutBlock v7, :new - Jump bb2(v5, v10, v6) - bb2(v12:BasicObject, v13:BasicObject, v14:NilClassExact): - Return v13 + v20:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008)) + v4:NilClassExact = Const Value(nil) + Jump bb1(v0, v4, v20) + bb1(v6:BasicObject, v7:NilClassExact, v8:BasicObject[VALUE(0x1008)]): + v11:BasicObject = SendWithoutBlock v8, :new + Jump bb2(v6, v11, v7) + bb2(v13:BasicObject, v14:BasicObject, v15:NilClassExact): + Return v14 "#]]); } @@ -5441,15 +5446,15 @@ mod opt_tests { bb0(v0:BasicObject): PatchPoint SingleRactorMode PatchPoint StableConstantNames(0x1000, C) - v21:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008)) - v3:NilClassExact = Const Value(nil) - v4:Fixnum[1] = Const Value(1) - Jump bb1(v0, v3, v21, v4) - bb1(v6:BasicObject, v7:NilClassExact, v8:BasicObject[VALUE(0x1008)], v9:Fixnum[1]): - v12:BasicObject = SendWithoutBlock v8, :new, v9 - Jump bb2(v6, v12, v7) - bb2(v14:BasicObject, v15:BasicObject, v16:NilClassExact): - Return v15 + v22:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008)) + v4:NilClassExact = Const Value(nil) + v5:Fixnum[1] = Const Value(1) + Jump bb1(v0, v4, v22, v5) + bb1(v7:BasicObject, v8:NilClassExact, v9:BasicObject[VALUE(0x1008)], v10:Fixnum[1]): + v13:BasicObject = SendWithoutBlock v9, :new, v10 + Jump bb2(v7, v13, v8) + bb2(v15:BasicObject, v16:BasicObject, v17:NilClassExact): + Return v16 "#]]); } |