Skip to content

Commit 392586d

Browse files
committed
ZJIT: Add patchpoint for tracing activation
1 parent 07eb3b6 commit 392586d

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
@@ -2186,6 +2186,30 @@ def foo = 1
21862186
}
21872187
end
21882188

2189+
def test_line_tracepoint_on_c_method
2190+
assert_compiles '[[:line, true]]', %q{
2191+
events = []
2192+
events.instance_variable_set(
2193+
:@tp,
2194+
TracePoint.new(:line) { |tp| events << [tp.event, tp.lineno] if tp.path == __FILE__ }
2195+
)
2196+
def events.to_str
2197+
@tp.enable; ''
2198+
end
2199+
2200+
# Stay in generated code while enabling tracing
2201+
def events.compiled(obj)
2202+
String(obj)
2203+
@tp.disable; __LINE__
2204+
end
2205+
2206+
line = events.compiled(events)
2207+
events[0][-1] = (events[0][-1] == line)
2208+
2209+
events
2210+
}
2211+
end
2212+
21892213
private
21902214

21912215
# Assert that every method call in `test_script` can be compiled by ZJIT

zjit/src/codegen.rs

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

66
use crate::asm::Label;
77
use crate::backend::current::{Reg, ALLOC_REGS};
8-
use crate::invariants::{track_bop_assumption, track_cme_assumption, track_single_ractor_assumption, track_stable_constant_names_assumption};
8+
use crate::invariants::{track_bop_assumption, track_cme_assumption, track_single_ractor_assumption, track_stable_constant_names_assumption, track_no_tracing_assumption};
99
use crate::gc::{append_gc_offsets, get_or_create_iseq_payload, get_or_create_iseq_payload_ptr, IseqPayload, IseqStatus};
1010
use crate::state::ZJITState;
1111
use crate::stats::incr_counter;
@@ -587,6 +587,10 @@ fn gen_patch_point(jit: &mut JITState, asm: &mut Assembler, invariant: &Invarian
587587
let side_exit_ptr = cb.resolve_label(label);
588588
track_stable_constant_names_assumption(idlist, code_ptr, side_exit_ptr, payload_ptr);
589589
}
590+
Invariant::NoTracing => {
591+
let side_exit_ptr = cb.resolve_label(label);
592+
track_no_tracing_assumption(code_ptr, side_exit_ptr, payload_ptr);
593+
}
590594
Invariant::SingleRactorMode => {
591595
let side_exit_ptr = cb.resolve_label(label);
592596
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
@@ -132,6 +132,8 @@ pub enum Invariant {
132132
StableConstantNames {
133133
idlist: *const ID,
134134
},
135+
/// TracePoint is enabled
136+
NoTracing,
135137
/// There is one ractor running. If a non-root ractor gets spawned, this is invalidated.
136138
SingleRactorMode,
137139
}
@@ -245,6 +247,7 @@ impl<'a> std::fmt::Display for InvariantPrinter<'a> {
245247
}
246248
write!(f, ")")
247249
}
250+
Invariant::NoTracing => write!(f, "NoTracing"),
248251
Invariant::SingleRactorMode => write!(f, "SingleRactorMode"),
249252
}
250253
}
@@ -3335,6 +3338,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
33353338
let args = state.stack_pop_n(argc as usize)?;
33363339
let recv = state.stack_pop()?;
33373340
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
3341+
fun.push_insn(block, Insn::PatchPoint { invariant: Invariant::NoTracing, state: exit_id });
33383342
let send = fun.push_insn(block, Insn::SendWithoutBlock { self_val: recv, cd, args, state: exit_id });
33393343
state.stack_push(send);
33403344
}
@@ -3358,6 +3362,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
33583362

33593363
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
33603364
let recv = fun.push_insn(block, Insn::Const { val: Const::Value(get_arg(pc, 0)) });
3365+
fun.push_insn(block, Insn::PatchPoint { invariant: Invariant::NoTracing, state: exit_id });
33613366
let send = fun.push_insn(block, Insn::SendWithoutBlock { self_val: recv, cd, args, state: exit_id });
33623367
state.stack_push(send);
33633368
}
@@ -3414,6 +3419,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
34143419
let args = state.stack_pop_n(argc as usize)?;
34153420
let recv = state.stack_pop()?;
34163421
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
3422+
fun.push_insn(block, Insn::PatchPoint { invariant: Invariant::NoTracing, state: exit_id });
34173423
let send = fun.push_insn(block, Insn::SendWithoutBlock { self_val: recv, cd, args, state: exit_id });
34183424
state.stack_push(send);
34193425
}
@@ -3511,6 +3517,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
35113517
.get_builtin_properties(&bf)
35123518
.map(|props| props.return_type);
35133519

3520+
fun.push_insn(block, Insn::PatchPoint { invariant: Invariant::NoTracing, state: exit_id });
35143521
let insn_id = fun.push_insn(block, Insn::InvokeBuiltin {
35153522
bf,
35163523
args,
@@ -3537,6 +3544,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
35373544
.get_builtin_properties(&bf)
35383545
.map(|props| props.return_type);
35393546

3547+
fun.push_insn(block, Insn::PatchPoint { invariant: Invariant::NoTracing, state: exit_id });
35403548
let insn_id = fun.push_insn(block, Insn::InvokeBuiltin {
35413549
bf,
35423550
args,

zjit/src/invariants.rs

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

55+
/// Set of patch points that assume that the C function call/return tracing is disabled
56+
no_tracing_patch_points: HashSet<PatchPoint>,
57+
5558
/// Set of patch points that assume that the interpreter is running with only one ractor
5659
single_ractor_patch_points: HashSet<PatchPoint>,
5760
}
@@ -270,6 +273,15 @@ pub extern "C" fn rb_zjit_before_ractor_spawn() {
270273
});
271274
}
272275

276+
pub fn track_no_tracing_assumption(patch_point_ptr: CodePtr, side_exit_ptr: CodePtr, payload_ptr: *mut IseqPayload) {
277+
let invariants = ZJITState::get_invariants();
278+
invariants.no_tracing_patch_points.insert(PatchPoint {
279+
patch_point_ptr,
280+
side_exit_ptr,
281+
payload_ptr,
282+
});
283+
}
284+
273285
#[unsafe(no_mangle)]
274286
pub extern "C" fn rb_zjit_tracing_invalidate_all() {
275287
use crate::gc::{for_each_iseq, get_or_create_iseq_payload, IseqStatus};
@@ -289,5 +301,13 @@ pub extern "C" fn rb_zjit_tracing_invalidate_all() {
289301
payload.status = IseqStatus::NotCompiled;
290302
unsafe { rb_iseq_reset_jit_func(iseq) };
291303
});
304+
305+
let cb = ZJITState::get_code_block();
306+
let patch_points = mem::take(&mut ZJITState::get_invariants().no_tracing_patch_points);
307+
308+
// Invalidate all patch points for no C function tracing
309+
compile_patch_points!(cb, patch_points, "No C function tracing, invalidating no C function tracing assumption");
310+
311+
cb.mark_all_executable();
292312
});
293313
}

0 commit comments

Comments
 (0)