Skip to content

Commit 26ce86b

Browse files
committed
ZJIT: Add patchpoint for tracing activation
1 parent 73854a4 commit 26ce86b

4 files changed

Lines changed: 57 additions & 1 deletion

File tree

test/ruby/test_zjit.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2240,6 +2240,30 @@ def foo = 1
22402240
}
22412241
end
22422242

2243+
def test_line_tracepoint_on_c_method
2244+
assert_compiles '[[:line, true]]', %q{
2245+
events = []
2246+
events.instance_variable_set(
2247+
:@tp,
2248+
TracePoint.new(:line) { |tp| events << [tp.event, tp.lineno] if tp.path == __FILE__ }
2249+
)
2250+
def events.to_str
2251+
@tp.enable; ''
2252+
end
2253+
2254+
# Stay in generated code while enabling tracing
2255+
def events.compiled(obj)
2256+
String(obj)
2257+
@tp.disable; __LINE__
2258+
end
2259+
2260+
line = events.compiled(events)
2261+
events[0][-1] = (events[0][-1] == line)
2262+
2263+
events
2264+
}
2265+
end
2266+
22432267
def test_opt_case_dispatch
22442268
assert_compiles '[true, false]', %q{
22452269
def test(x)

zjit/src/codegen.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::slice;
99

1010
use crate::asm::Label;
1111
use crate::backend::current::{Reg, ALLOC_REGS};
12-
use crate::invariants::{track_bop_assumption, track_cme_assumption, track_single_ractor_assumption, track_stable_constant_names_assumption};
12+
use crate::invariants::{track_bop_assumption, track_cme_assumption, track_single_ractor_assumption, track_stable_constant_names_assumption, track_no_tracing_assumption};
1313
use crate::gc::{append_gc_offsets, get_or_create_iseq_payload, get_or_create_iseq_payload_ptr, IseqPayload, IseqStatus};
1414
use crate::state::ZJITState;
1515
use crate::stats::{exit_counter_for_compile_error, incr_counter, incr_counter_by, CompileError};
@@ -593,6 +593,10 @@ fn gen_patch_point(jit: &mut JITState, asm: &mut Assembler, invariant: &Invarian
593593
let side_exit_ptr = cb.resolve_label(label);
594594
track_stable_constant_names_assumption(idlist, code_ptr, side_exit_ptr, payload_ptr);
595595
}
596+
Invariant::NoTracing => {
597+
let side_exit_ptr = cb.resolve_label(label);
598+
track_no_tracing_assumption(code_ptr, side_exit_ptr, payload_ptr);
599+
}
596600
Invariant::SingleRactorMode => {
597601
let side_exit_ptr = cb.resolve_label(label);
598602
track_single_ractor_assumption(code_ptr, side_exit_ptr, payload_ptr);

zjit/src/hir.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ pub enum Invariant {
134134
StableConstantNames {
135135
idlist: *const ID,
136136
},
137+
/// TracePoint is enabled
138+
NoTracing,
137139
/// There is one ractor running. If a non-root ractor gets spawned, this is invalidated.
138140
SingleRactorMode,
139141
}
@@ -247,6 +249,7 @@ impl<'a> std::fmt::Display for InvariantPrinter<'a> {
247249
}
248250
write!(f, ")")
249251
}
252+
Invariant::NoTracing => write!(f, "NoTracing"),
250253
Invariant::SingleRactorMode => write!(f, "SingleRactorMode"),
251254
}
252255
}
@@ -3399,6 +3402,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
33993402
let args = state.stack_pop_n(argc as usize)?;
34003403
let recv = state.stack_pop()?;
34013404
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
3405+
fun.push_insn(block, Insn::PatchPoint { invariant: Invariant::NoTracing, state: exit_id });
34023406
let send = fun.push_insn(block, Insn::SendWithoutBlock { self_val: recv, cd, args, state: exit_id });
34033407
state.stack_push(send);
34043408
}
@@ -3422,6 +3426,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
34223426

34233427
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
34243428
let recv = fun.push_insn(block, Insn::Const { val: Const::Value(get_arg(pc, 0)) });
3429+
fun.push_insn(block, Insn::PatchPoint { invariant: Invariant::NoTracing, state: exit_id });
34253430
let send = fun.push_insn(block, Insn::SendWithoutBlock { self_val: recv, cd, args, state: exit_id });
34263431
state.stack_push(send);
34273432
}
@@ -3478,6 +3483,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
34783483
let args = state.stack_pop_n(argc as usize)?;
34793484
let recv = state.stack_pop()?;
34803485
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
3486+
fun.push_insn(block, Insn::PatchPoint { invariant: Invariant::NoTracing, state: exit_id });
34813487
let send = fun.push_insn(block, Insn::SendWithoutBlock { self_val: recv, cd, args, state: exit_id });
34823488
state.stack_push(send);
34833489
}
@@ -3575,6 +3581,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
35753581
.get_builtin_properties(&bf)
35763582
.map(|props| props.return_type);
35773583

3584+
fun.push_insn(block, Insn::PatchPoint { invariant: Invariant::NoTracing, state: exit_id });
35783585
let insn_id = fun.push_insn(block, Insn::InvokeBuiltin {
35793586
bf,
35803587
args,
@@ -3601,6 +3608,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
36013608
.get_builtin_properties(&bf)
36023609
.map(|props| props.return_type);
36033610

3611+
fun.push_insn(block, Insn::PatchPoint { invariant: Invariant::NoTracing, state: exit_id });
36043612
let insn_id = fun.push_insn(block, Insn::InvokeBuiltin {
36053613
bf,
36063614
args,

zjit/src/invariants.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ pub struct Invariants {
5454
/// Map from constant ID to patch points that assume the constant hasn't been redefined
5555
constant_state_patch_points: HashMap<ID, HashSet<PatchPoint>>,
5656

57+
/// Set of patch points that assume that the C function call/return tracing is disabled
58+
no_tracing_patch_points: HashSet<PatchPoint>,
59+
5760
/// Set of patch points that assume that the interpreter is running with only one ractor
5861
single_ractor_patch_points: HashSet<PatchPoint>,
5962
}
@@ -272,6 +275,15 @@ pub extern "C" fn rb_zjit_before_ractor_spawn() {
272275
});
273276
}
274277

278+
pub fn track_no_tracing_assumption(patch_point_ptr: CodePtr, side_exit_ptr: CodePtr, payload_ptr: *mut IseqPayload) {
279+
let invariants = ZJITState::get_invariants();
280+
invariants.no_tracing_patch_points.insert(PatchPoint {
281+
patch_point_ptr,
282+
side_exit_ptr,
283+
payload_ptr,
284+
});
285+
}
286+
275287
#[unsafe(no_mangle)]
276288
pub extern "C" fn rb_zjit_tracing_invalidate_all() {
277289
use crate::gc::{get_or_create_iseq_payload, IseqStatus};
@@ -291,5 +303,13 @@ pub extern "C" fn rb_zjit_tracing_invalidate_all() {
291303
payload.status = IseqStatus::NotCompiled;
292304
unsafe { rb_iseq_reset_jit_func(iseq) };
293305
});
306+
307+
let cb = ZJITState::get_code_block();
308+
let patch_points = mem::take(&mut ZJITState::get_invariants().no_tracing_patch_points);
309+
310+
// Invalidate all patch points for no tracing
311+
compile_patch_points!(cb, patch_points, "TracePoint is enabled, invalidating no tracing assumption");
312+
313+
cb.mark_all_executable();
294314
});
295315
}

0 commit comments

Comments
 (0)