8000 ZJIT: Add codegen (and FrameState) for GetConstPath · ruby/ruby@0933400 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0933400

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. Add FrameState to GetConstPath to get access to the PC.
1 parent 01ff17f commit 0933400

File tree

3 files changed

+86
-44
lines changed

3 files changed

+86
-44
lines changed

test/ruby/test_zjit.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,27 @@ def test() = @foo = 1
678678
}
679679
end
680680

681+
def test_uncached_getconstant_path
682+
assert_compiles RUBY_COPYRIGHT.dump, %q{
683+
def test = RUBY_COPYRIGHT
684+
test
685+
}, call_threshold: 1, insns: [:opt_getconstant_path]
686+
end
687+
688+
def test_getconstant_path_autoload
689+
# A constant-referencing expression can run arbitrary code through Kernel#autoload.
690+
Dir.mktmpdir('autoload') do |tmpdir|
691+
autoload_path = File.join(tmpdir, 'test_getconstant_path_autoload.rb')
692+
File.write(autoload_path, 'X = RUBY_COPYRIGHT')
693+
694+
assert_compiles RUBY_COPYRIGHT.dump, %Q{
695+
Object.autoload(:X, #{File.realpath(autoload_path).inspect})
696+
def test = X
697+
test
698+
}, call_threshold: 1, insns: [:opt_getconstant_path]
699+
end
700+
end
701+
681702
def test_send_backtrace
682703
backtrace = [
683704
"-e:2:in 'Object#jit_frame1'",

zjit/src/codegen.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
278278
Insn::GetIvar { self_val, id, state: _ } => gen_getivar(asm, opnd!(self_val), *id),
279279
Insn::SetGlobal { id, val, state: _ } => gen_setglobal(asm, *id, opnd!(val)),
280280
Insn::GetGlobal { id, state: _ } => gen_getglobal(asm, *id),
281+
Insn::GetConstantPath { ic, state } => gen_get_constant_path(asm, *ic, &function.frame_state(*state)),
281282
Insn::SetIvar { self_val, id, val, state: _ } => return gen_setivar(asm, opnd!(self_val), *id, opnd!(val)),
282283
Insn::SideExit { state } => return gen_side_exit(jit, asm, &function.frame_state(*state)),
283284
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
295296
Some(())
296297
}
297298

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

zjit/src/hir.rs

Lines changed: 49 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ pub enum Insn {
431431
/// Return C `true` if `val` is `Qnil`, else `false`.
432432
IsNil { val: InsnId },
433433
Defined { op_type: usize, obj: VALUE, pushval: VALUE, v: InsnId },
434-
GetConstantPath { ic: *const iseq_inline_constant_cache },
434+
GetConstantPath { ic: *const iseq_inline_constant_cache, state: InsnId },
435435

436436
/// Get a global variable named `id`
437437
GetGlobal { id: ID, state: InsnId },
@@ -651,7 +651,7 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
651651
Insn::GuardType { val, guard_type, .. } => { write!(f, "GuardType {val}, {}", guard_type.print(self.ptr_map)) },
652652
Insn::GuardBitEquals { val, expected, .. } => { write!(f, "GuardBitEquals {val}, {}", expected.print(self.ptr_map)) },
653653
Insn::PatchPoint(invariant) => { write!(f, "PatchPoint {}", invariant.print(self.ptr_map)) },
654-
Insn::GetConstantPath { ic } => { write!(f, "GetConstantPath {:p}", self.ptr_map.map_ptr(ic)) },
654+
Insn::GetConstantPath { ic, .. } => { write!(f, "GetConstantPath {:p}", self.ptr_map.map_ptr(ic)) },
655655
Insn::CCall { cfun, args, name, return_type: _, elidable: _ } => {
656656
write!(f, "CCall {}@{:p}", name.contents_lossy(), self.ptr_map.map_ptr(cfun))?;
657657
for arg in args {
@@ -1355,7 +1355,7 @@ impl Function {
13551355
let send_direct = self.push_insn(block, Insn::SendWithoutBlockDirect { self_val, call_info, cd, cme, iseq, args, state });
13561356
self.make_equal_to(insn_id, send_direct);
13571357
}
1358-
Insn::GetConstantPath { ic } => {
1358+
Insn::GetConstantPath { ic, .. } => {
13591359
let idlist: *const ID = unsafe { (*ic).segments };
13601360
let ice = unsafe { (*ic).entry };
13611361
if ice.is_null() {
@@ -1642,10 +1642,14 @@ impl Function {
16421642
if necessary[insn_id.0] { continue; }
16431643
necessary[insn_id.0] = true;
16441644
match self.find(insn_id) {
1645-
Insn::Const { .. } | Insn::Param { .. }
1646-
| Insn::PatchPoint(..) | Insn::GetConstantPath { .. }
1645+
Insn::Const { .. }
1646+
| Insn::Param { .. }
1647+
| Insn::PatchPoint(..)
16471648
| Insn::PutSpecialObject { .. } =>
16481649
{}
1650+
Insn::GetConstantPath { ic: _, state } => {
1651+
worklist.push_back(state);
1652+
}
16491653
Insn::ArrayMax { elements, state }
16501654
| Insn::NewArray { elements, state } => {
16511655
worklist.extend(elements);
@@ -2309,7 +2313,8 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
23092313
}
23102314
YARVINSN_opt_getconstant_path => {
23112315
let ic = get_arg(pc, 0).as_ptr();
2312-
state.stack_push(fun.push_insn(block, Insn::GetConstantPath { ic }));
2316+
let snapshot = fun.push_insn(block, Insn::Snapshot { state: exit_state });
2317+
state.stack_push(fun.push_insn(block, Insn::GetConstantPath { ic, state: snapshot }));
23132318
}
23142319
YARVINSN_branchunless => {
23152320
let offset = get_arg(pc, 0).as_i64();
@@ -3745,14 +3750,14 @@ mod tests {
37453750
assert_method_hir_with_opcode("test", YARVINSN_opt_new, expect![[r#"
37463751
fn test:
37473752
bb0(v0:BasicObject):
3748-
v2:BasicObject = GetConstantPath 0x1000
3749-
v3:NilClassExact = Const Value(nil)
3750-
Jump bb1(v0, v3, v2)
3751-
bb1(v5:BasicObject, v6:NilClassExact, v7:BasicObject):
3752-
v10:BasicObject = SendWithoutBlock v7, :new
3753-
Jump bb2(v5, v10, v6)
3754-
bb2(v12:BasicObject, v13:BasicObject, v14:NilClassExact):
3755-
Return v13
3753+
v3:BasicObject = GetConstantPath 0x1000
3754+
v4:NilClassExact = Const Value(nil)
3755+
Jump bb1(v0, v4, v3)
3756+
bb1(v6:BasicObject, v7:NilClassExact, v8:BasicObject):
3757+
v11:BasicObject = SendWithoutBlock v8, :new
3758+
Jump bb2(v6, v11, v7)
3759+
bb2(v13:BasicObject, v14:BasicObject, v15:NilClassExact):
3760+
Return v14
37563761
"#]]);
37573762
}
37583763

@@ -5155,9 +5160,9 @@ mod opt_tests {
51555160
assert_optimized_method_hir("test", expect![[r#"
51565161
fn test:
51575162
bb0(v0:BasicObject):
5158-
v2:BasicObject = GetConstantPath 0x1000
5159-
v3:Fixnum[5] = Const Value(5)
5160-
Return v3
5163+
v3:BasicObject = GetConstantPath 0x1000
5164+
v4:Fixnum[5] = Const Value(5)
5165+
Return v4
51615166
"#]]);
51625167
}
51635168

@@ -5226,8 +5231,8 @@ mod opt_tests {
52265231
PatchPoint SingleRactorMode
52275232
PatchPoint StableConstantNames(0x1000, M)
52285233
PatchPoint MethodRedefined(Module@0x1008, name@0x1010)
5229-
v6:Fixnum[1] = Const Value(1)
5230-
Return v6
5234+
v7:Fixnum[1] = Const Value(1)
5235+
Return v7
52315236
"#]]);
52325237
}
52335238

@@ -5344,8 +5349,8 @@ mod opt_tests {
53445349
assert_optimized_method_hir("test", expect![[r#"
53455350
fn test:
53465351
bb0(v0:BasicObject):
5347-
v2:BasicObject = GetConstantPath 0x1000
5348-
Return v2
5352+
v3:BasicObject = GetConstantPath 0x1000
5353+
Return v3
53495354
"#]]);
53505355
}
53515356

@@ -5359,8 +5364,8 @@ mod opt_tests {
53595364
assert_optimized_method_hir("test", expect![[r#"
53605365
fn test:
53615366
bb0(v0:BasicObject):
5362-
v2:BasicObject = GetConstantPath 0x1000
5363-
Return v2
5367+
v3:BasicObject = GetConstantPath 0x1000
5368+
Return v3
53645369
"#]]);
53655370
}
53665371

@@ -5375,8 +5380,8 @@ mod opt_tests {
53755380
bb0(v0:BasicObject):
53765381
PatchPoint SingleRactorMode
53775382
PatchPoint StableConstantNames(0x1000, Kernel)
5378-
v6:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5379-
Return v6
5383+
v7:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5384+
Return v7
53805385
"#]]);
53815386
}
53825387

@@ -5397,8 +5402,8 @@ mod opt_tests {
53975402
bb0(v0:BasicObject):
53985403
PatchPoint SingleRactorMode
53995404
PatchPoint StableConstantNames(0x1000, Foo::Bar::C)
5400-
v6:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5401-
Return v6
5405+
v7:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5406+
Return v7
54025407
"#]]);
54035408
}
54045409

@@ -5414,14 +5419,14 @@ mod opt_tests {
54145419
bb0(v0:BasicObject):
54155420
PatchPoint SingleRactorMode
54165421
PatchPoint StableConstantNames(0x1000, C)
5417-
v19:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5418-
v3:NilClassExact = Const Value(nil)
5419-
Jump bb1(v0, v3, v19)
5420-
bb1(v5:BasicObject, v6:NilClassExact, v7:BasicObject[VALUE(0x1008)]):
5421-
v10:BasicObject = SendWithoutBlock v7, :new
5422-
Jump bb2(v5, v10, v6)
5423-
bb2(v12:BasicObject, v13:BasicObject, v14:NilClassExact):
5424-
Return v13
5422+
v20:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5423+
v4:NilClassExact = Const Value(nil)
5424+
Jump bb1(v0, v4, v20)
5425+
bb1(v6:BasicObject, v7:NilClassExact, v8:BasicObject[VALUE(0x1008)]):
5426+
v11:BasicObject = SendWithoutBlock v8, :new
5427+
Jump bb2(v6, v11, v7)
5428+
bb2(v13:BasicObject, v14:BasicObject, v15:NilClassExact):
5429+
Return v14
54255430
"#]]);
54265431
}
54275432

@@ -5441,15 +5446,15 @@ mod opt_tests {
54415446
bb0(v0:BasicObject):
54425447
PatchPoint SingleRactorMode
54435448
PatchPoint StableConstantNames(0x1000, C)
5444-
v21:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5445-
v3:NilClassExact = Const Value(nil)
5446-
v4:Fixnum[1] = Const Value(1)
5447-
Jump bb1(v0, v3, v21, v4)
5448-
bb1(v6:BasicObject, v7:NilClassExact, v8:BasicObject[VALUE(0x1008)], v9:Fixnum[1]):
5449-
v12:BasicObject = SendWithoutBlock v8, :new, v9
5450-
Jump bb2(v6, v12, v7)
5451-
bb2(v14:BasicObject, v15:BasicObject, v16:NilClassExact):
5452-
Return v15
5449+
v22:BasicObject[VALUE(0x1008)] = Const Value(VALUE(0x1008))
5450+
v4:NilClassExact = Const Value(nil)
5451+
v5:Fixnum[1] = Const Value(1)
5452+
Jump bb1(v0, v4, v22, v5)
5453+
bb1(v7:BasicObject, v8:NilClassExact, v9:BasicObject[VALUE(0x1008)], v10:Fixnum[1]):
5454+
v13:BasicObject = SendWithoutBlock v9, :new, v10
5455+
Jump bb2(v7, v13, v8)
5456+
bb2(v15:BasicObject, v16:BasicObject, v17:NilClassExact):
5457+
Return v16
54535458
"#]]);
54545459
}
54555460

0 commit comments

Comments
 (0)
0