Skip to content

Commit 9fef4d0

Browse files
committed
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. To have the PC, GetConstPath now has a FrameState.
1 parent 260ac23 commit 9fef4d0

3 files changed

Lines changed: 83 additions & 43 deletions

File tree

test/ruby/test_zjit.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,26 @@ def test() = @foo = 1
636636
}
637637
end
638638

639+
def test_uncached_getconstant_path
640+
assert_compiles RUBY_COPYRIGHT.dump, %q{
641+
def test = RUBY_COPYRIGHT
642+
test
643+
}, call_threshold: 1, insns: [:opt_getconstant_path]
644+
end
645+
646+
def test_getconstant_path_autoload
647+
Dir.mktmpdir('autoload') do |tmpdir|
648+
autoload_path = File.join(tmpdir, "test_getconstant_path_autoload.rb")
649+
File.write(autoload_path, 'X = RUBY_COPYRIGHT')
650+
651+
assert_compiles RUBY_COPYRIGHT.dump, %Q{
652+
Object.autoload(:X, #{File.realpath(autoload_path).inspect})
653+
def test = X
654+
test
655+
}, call_threshold: 1
656+
end
657+
end
658+
639659
def test_send_backtrace
640660
backtrace = [
641661
"-e:2:in 'Object#jit_frame1'",

zjit/src/codegen.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
277277
Insn::GetIvar { self_val, id, state: _ } => gen_getivar(asm, opnd!(self_val), *id),
278278
Insn::SetGlobal { id, val, state: _ } => gen_setglobal(asm, *id, opnd!(val)),
279279
Insn::GetGlobal { id, state: _ } => gen_getglobal(asm, *id),
280+
Insn::GetConstantPath { ic, state } => gen_get_constant_path(asm, *ic, &function.frame_state(*state)),
280281
Insn::SetIvar { self_val, id, val, state: _ } => return gen_setivar(asm, opnd!(self_val), *id, opnd!(val)),
281282
Insn::SideExit { state } => return gen_side_exit(jit, asm, &function.frame_state(*state)),
282283
_ => {
@@ -293,6 +294,21 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
293294
Some(())
294295
}
295296

297+
fn gen_get_constant_path(asm: &mut Assembler, ic: *const iseq_inline_constant_cache, state: &FrameState) -> Opnd {
298+
unsafe extern "C" {
299+
fn rb_vm_opt_getconstant_path(ec: EcPtr, cfp: CfpPtr, ic: *const iseq_inline_constant_cache) -> VALUE;
300+
}
301+
302+
// Save PC since the call can allocate an IC
303+
gen_save_pc(asm, state);
304+
305+
let val = asm.ccall(
306+
rb_vm_opt_getconstant_path as *const u8,
307+
vec![EC, CFP, Opnd::const_ptr(ic as *const u8)],
308+
);
309+
val
310+
}
311+
296312
/// Lowering for [`Insn::CCall`]. This is a low-level raw call that doesn't know
297313
/// anything about the callee, so handling for e.g. GC safety is dealt with elsewhere.
298314
fn gen_ccall(jit: &mut JITState, asm: &mut Assembler, cfun: *const u8, args: &[InsnId]) -> Option<lir::Opnd> {

zjit/src/hir.rs

Lines changed: 47 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ pub enum Insn {
390390
/// Return C `true` if `val` is `Qnil`, else `false`.
391391
IsNil { val: InsnId },
392392
Defined { op_type: usize, obj: VALUE, pushval: VALUE, v: InsnId },
393-
GetConstantPath { ic: *const iseq_inline_constant_cache },
393+
GetConstantPath { ic: *const iseq_inline_constant_cache, state: InsnId },
394394

395395
/// Get a global variable named `id`
396396
GetGlobal { id: ID, state: InsnId },
@@ -610,7 +610,7 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
610610
Insn::GuardType { val, guard_type, .. } => { write!(f, "GuardType {val}, {}", guard_type.print(self.ptr_map)) },
611611
Insn::GuardBitEquals { val, expected, .. } => { write!(f, "GuardBitEquals {val}, {}", expected.print(self.ptr_map)) },
612612
Insn::PatchPoint(invariant) => { write!(f, "PatchPoint {}", invariant.print(self.ptr_map)) },
613-
Insn::GetConstantPath { ic } => { write!(f, "GetConstantPath {:p}", self.ptr_map.map_ptr(ic)) },
613+
Insn::GetConstantPath { ic, .. } => { write!(f, "GetConstantPath {:p}", self.ptr_map.map_ptr(ic)) },
614614
Insn::CCall { cfun, args, name, return_type: _, elidable: _ } => {
615615
write!(f, "CCall {}@{:p}", name.contents_lossy(), self.ptr_map.map_ptr(cfun))?;
616616
for arg in args {
@@ -1273,7 +1273,7 @@ impl Function {
12731273
let send_direct = self.push_insn(block, Insn::SendWithoutBlockDirect { self_val, call_info, cd, cme, iseq, args, state });
12741274
self.make_equal_to(insn_id, send_direct);
12751275
}
1276-
Insn::GetConstantPath { ic } => {
1276+
Insn::GetConstantPath { ic, .. } => {
12771277
let idlist: *const ID = unsafe { (*ic).segments };
12781278
let ice = unsafe { (*ic).entry };
12791279
if ice.is_null() {
@@ -1561,8 +1561,11 @@ impl Function {
15611561
necessary[insn_id.0] = true;
15621562
match self.find(insn_id) {
15631563
Insn::Const { .. } | Insn::Param { .. }
1564-
| Insn::PatchPoint(..) | Insn::GetConstantPath { .. } =>
1564+
| Insn::PatchPoint(..) =>
15651565
{}
1566+
Insn::GetConstantPath { ic: _, state } => {
1567+
worklist.push_back(state);
1568+
}
15661569
Insn::ArrayMax { elements, state }
15671570
| Insn::NewArray { elements, state } => {
15681571
worklist.extend(elements);
@@ -2218,7 +2221,8 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
22182221
}
22192222
YARVINSN_opt_getconstant_path => {
22202223
let ic = get_arg(pc, 0).as_ptr();
2221-
state.stack_push(fun.push_insn(block, Insn::GetConstantPath { ic }));
2224+
let snapshot = fun.push_insn(block, Insn::Snapshot { state: exit_state });
2225+
state.stack_push(fun.push_insn(block, Insn::GetConstantPath { ic, state: snapshot }));
22222226
}
22232227
YARVINSN_branchunless => {
22242228
let offset = get_arg(pc, 0).as_i64();
@@ -3563,14 +3567,14 @@ mod tests {
35633567
assert_method_hir_with_opcode("test", YARVINSN_opt_new, expect![[r#"
35643568
fn test:
35653569
bb0(v0:BasicObject):
3566-
v2:BasicObject = GetConstantPath 0x1000
3567-
v3:NilClassExact = Const Value(nil)
3568-
Jump bb1(v0, v3, v2)
3569-
bb1(v5:BasicObject, v6:NilClassExact, v7:BasicObject):
3570-
v10:BasicObject = SendWithoutBlock v7, :new
3571-
Jump bb2(v5, v10, v6)
3572-
bb2(v12:BasicObject, v13:BasicObject, v14:NilClassExact):
3573-
Return v13
3570+
v3:BasicObject = GetConstantPath 0x1000
3571+
v4:NilClassExact = Const Value(nil)
3572+
Jump bb1(v0, v4, v3)
3573+
bb1(v6:BasicObject, v7:NilClassExact, v8:BasicObject):
3574+
v11:BasicObject = SendWithoutBlock v8, :new
3575+
Jump bb2(v6, v11, v7)
3576+
bb2(v13:BasicObject, v14:BasicObject, v15:NilClassExact):
3577+
Return v14
35743578
"#]]);
35753579
}
35763580

@@ -4952,9 +4956,9 @@ mod opt_tests {
49524956
assert_optimized_method_hir("test", expect![[r#"
49534957
fn test:
49544958
bb0(v0:BasicObject):
4955-
v2:BasicObject = GetConstantPath 0x1000
4956-
v3:Fixnum[5] = Const Value(5)
4957-
Return v3
4959+
v3:BasicObject = GetConstantPath 0x1000
4960+
v4:Fixnum[5] = Const Value(5)
4961+
Return v4
49584962
"#]]);
49594963
}
49604964

@@ -5023,8 +5027,8 @@ mod opt_tests {
50235027
PatchPoint SingleRactorMode
50245028
PatchPoint StableConstantNames(0x1000, M)
50255029
PatchPoint MethodRedefined(Module@0x1008, name@0x1010)
5026-
v6:Fixnum[1] = Const Value(1)
5027-
Return v6
5030+
v7:Fixnum[1] = Const Value(1)
5031+
Return v7
50285032
"#]]);
50295033
}
50305034

@@ -5141,8 +5145,8 @@ mod opt_tests {
51415145
assert_optimized_method_hir("test", expect![[r#"
51425146
fn test:
51435147
bb0(v0:BasicObject):
5144-
v2:BasicObject = GetConstantPath 0x1000
5145-
Return v2
5148+
v3:BasicObject = GetConstantPath 0x1000
5149+
Return v3
51465150
"#]]);
51475151
}
51485152

@@ -5156,8 +5160,8 @@ mod opt_tests {
51565160
assert_optimized_method_hir("test", expect![[r#"
51575161
fn test:
51585162
bb0(v0:BasicObject):
5159-
v2:BasicObject = GetConstantPath 0x1000
5160-
Return v2
5163+
v3:BasicObject = GetConstantPath 0x1000
5164+
Return v3
51615165
"#]]);
51625166
}
51635167

@@ -5172,8 +5176,8 @@ mod opt_tests {
51725176
bb0(v0:BasicObject):
51735177
PatchPoint SingleRactorMode
51745178
PatchPoint StableConstantNames(0x1000, Kernel)
5175-
v6:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5176-
Return v6
5179+
v7:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5180+
Return v7
51775181
"#]]);
51785182
}
51795183

@@ -5194,8 +5198,8 @@ mod opt_tests {
51945198
bb0(v0:BasicObject):
51955199
PatchPoint SingleRactorMode
51965200
PatchPoint StableConstantNames(0x1000, Foo::Bar::C)
5197-
v6:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5198-
Return v6
5201+
v7:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5202+
Return v7
51995203
"#]]);
52005204
}
52015205

@@ -5211,14 +5215,14 @@ mod opt_tests {
52115215
bb0(v0:BasicObject):
52125216
PatchPoint SingleRactorMode
52135217
PatchPoint StableConstantNames(0x1000, C)
5214-
v19:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5215-
v3:NilClassExact = Const Value(nil)
5216-
Jump bb1(v0, v3, v19)
5217-
bb1(v5:BasicObject, v6:NilClassExact, v7:BasicObject[VALUE(0x1008)]):
5218-
v10:BasicObject = SendWithoutBlock v7, :new
5219-
Jump bb2(v5, v10, v6)
5220-
bb2(v12:BasicObject, v13:BasicObject, v14:NilClassExact):
5221-
Return v13
5218+
v20:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5219+
v4:NilClassExact = Const Value(nil)
5220+
Jump bb1(v0, v4, v20)
5221+
bb1(v6:BasicObject, v7:NilClassExact, v8:BasicObject[VALUE(0x1008)]):
5222+
v11:BasicObject = SendWithoutBlock v8, :new
5223+
Jump bb2(v6, v11, v7)
5224+
bb2(v13:BasicObject, v14:BasicObject, v15:NilClassExact):
5225+
Return v14
52225226
"#]]);
52235227
}
52245228

@@ -5238,15 +5242,15 @@ mod opt_tests {
52385242
bb0(v0:BasicObject):
52395243
PatchPoint SingleRactorMode
52405244
PatchPoint StableConstantNames(0x1000, C)
5241-
v21:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5242-
v3:NilClassExact = Const Value(nil)
5243-
v4:Fixnum[1] = Const Value(1)
5244-
Jump bb1(v0, v3, v21, v4)
5245-
bb1(v6:BasicObject, v7:NilClassExact, v8:BasicObject[VALUE(0x1008)], v9:Fixnum[1]):
5246-
v12:BasicObject = SendWithoutBlock v8, :new, v9
5247-
Jump bb2(v6, v12, v7)
5248-
bb2(v14:BasicObject, v15:BasicObject, v16:NilClassExact):
5249-
Return v15
5245+
v22:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5246+
v4:NilClassExact = Const Value(nil)
5247+
v5:Fixnum[1] = Const Value(1)
5248+
Jump bb1(v0, v4, v22, v5)
5249+
bb1(v7:BasicObject, v8:NilClassExact, v9:BasicObject[VALUE(0x1008)], v10:Fixnum[1]):
5250+
v13:BasicObject = SendWithoutBlock v9, :new, v10
5251+
Jump bb2(v7, v13, v8)
5252+
bb2(v15:BasicObject, v16:BasicObject, v17:NilClassExact):
5253+
Return v16
52505254
"#]]);
52515255
}
52525256

0 commit comments

Comments
 (0)