summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <[email protected]>2024-08-08 16:13:16 -0700
committerGitHub <[email protected]>2024-08-08 16:13:16 -0700
commit77ffdfe79fc9dc0b327ff88ea3df4082183c08f6 (patch)
treec078ab5431c2cd8934edeaedab2f5e2d1e6792a1
parentec5436bc3a8e7c616a9b88c08d766180894ea82d (diff)
YJIT: Allow tracing fallback counters (#11347)
* YJIT: Allow tracing fallback counters * Update yjit.md about --yjit-trace-exits=counter
Notes
Notes: Merged-By: k0kubun <[email protected]>
-rw-r--r--doc/yjit/yjit.md2
-rw-r--r--yjit/src/codegen.rs319
-rw-r--r--yjit/src/options.rs6
3 files changed, 174 insertions, 153 deletions
diff --git a/doc/yjit/yjit.md b/doc/yjit/yjit.md
index b2769a0f5d..c63d31b64f 100644
--- a/doc/yjit/yjit.md
+++ b/doc/yjit/yjit.md
@@ -179,7 +179,7 @@ YJIT supports all command-line options supported by upstream CRuby, but also add
This can allow you to use a lower executable memory size limit, but may cause a slight drop in performance when the limit is hit.
- `--yjit-perf`: enable frame pointers and profiling with the `perf` tool
- `--yjit-trace-exits`: produce a Marshal dump of backtraces from all exits. Automatically enables `--yjit-stats`
-- `--yjit-trace-exits=COUNTER`: produce a Marshal dump of backtraces from specified exits. Automatically enables `--yjit-stats`
+- `--yjit-trace-exits=COUNTER`: produce a Marshal dump of backtraces from a counted exit or a fallback. Automatically enables `--yjit-stats`
- `--yjit-trace-exits-sample-rate=N`: trace exit locations only every Nth occurrence. Automatically enables `--yjit-trace-exits`
Note that there is also an environment variable `RUBY_YJIT_ENABLE` which can be used to enable YJIT.
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index a9b3a2dcda..458777b5e3 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -460,8 +460,31 @@ pub enum JCCKinds {
JCC_JO_MUL,
}
+/// Generate code to increment a given counter. With --yjit-trace-exits=counter,
+/// the counter is traced when it's incremented by this function.
#[inline(always)]
-fn gen_counter_incr(asm: &mut Assembler, counter: Counter) {
+fn gen_counter_incr(jit: &JITState, asm: &mut Assembler, counter: Counter) {
+ gen_counter_incr_with_pc(asm, counter, jit.pc);
+}
+
+/// Same as gen_counter_incr(), but takes PC isntead of JITState.
+#[inline(always)]
+fn gen_counter_incr_with_pc(asm: &mut Assembler, counter: Counter, pc: *mut VALUE) {
+ gen_counter_incr_without_pc(asm, counter);
+
+ // Trace a counter if --yjit-trace-exits=counter is given.
+ // TraceExits::All is handled by gen_exit().
+ if get_option!(trace_exits) == Some(TraceExits::Counter(counter)) {
+ with_caller_saved_temp_regs(asm, |asm| {
+ asm.ccall(rb_yjit_record_exit_stack as *const u8, vec![Opnd::const_ptr(pc as *const u8)]);
+ });
+ }
+}
+
+/// Generate code to increment a given counter. Not traced by --yjit-trace-exits=counter
+/// unlike gen_counter_incr() or gen_counter_incr_with_pc().
+#[inline(always)]
+fn gen_counter_incr_without_pc(asm: &mut Assembler, counter: Counter) {
// Assert that default counters are not incremented by generated code as this would impact performance
assert!(!DEFAULT_COUNTERS.contains(&counter), "gen_counter_incr incremented {:?}", counter);
@@ -723,7 +746,7 @@ fn gen_stub_exit(ocb: &mut OutlinedCb) -> Option<CodePtr> {
let ocb = ocb.unwrap();
let mut asm = Assembler::new_without_iseq();
- gen_counter_incr(&mut asm, Counter::exit_from_branch_stub);
+ gen_counter_incr_without_pc(&mut asm, Counter::exit_from_branch_stub);
asm_comment!(asm, "exit from branch stub");
asm.cpop_into(SP);
@@ -833,15 +856,7 @@ pub fn gen_counted_exit(exit_pc: *mut VALUE, side_exit: CodePtr, ocb: &mut Outli
let mut asm = Assembler::new_without_iseq();
// Increment a counter
- gen_counter_incr(&mut asm, counter);
-
- // Trace a counted exit if --yjit-trace-exits=counter is given.
- // TraceExits::All is handled by gen_exit().
- if get_option!(trace_exits) == Some(TraceExits::CountedExit(counter)) {
- with_caller_saved_temp_regs(&mut asm, |asm| {
- asm.ccall(rb_yjit_record_exit_stack as *const u8, vec![Opnd::const_ptr(exit_pc as *const u8)]);
- });
- }
+ gen_counter_incr_with_pc(&mut asm, counter, exit_pc);
// Jump to the existing side exit
asm.jmp(Target::CodePtr(side_exit));
@@ -901,7 +916,7 @@ fn gen_full_cfunc_return(ocb: &mut OutlinedCb) -> Option<CodePtr> {
);
// Count the exit
- gen_counter_incr(&mut asm, Counter::traced_cfunc_return);
+ gen_counter_incr_without_pc(&mut asm, Counter::traced_cfunc_return);
// Return to the interpreter
asm.cpop_into(SP);
@@ -926,7 +941,7 @@ fn gen_leave_exit(ocb: &mut OutlinedCb) -> Option<CodePtr> {
let ret_opnd = asm.live_reg_opnd(C_RET_OPND);
// Every exit to the interpreter should be counted
- gen_counter_incr(&mut asm, Counter::leave_interp_return);
+ gen_counter_incr_without_pc(&mut asm, Counter::leave_interp_return);
asm_comment!(asm, "exit from leave");
asm.cpop_into(SP);
@@ -952,7 +967,7 @@ fn gen_leave_exception(ocb: &mut OutlinedCb) -> Option<CodePtr> {
let ruby_ret_val = asm.live_reg_opnd(C_RET_OPND);
// Every exit to the interpreter should be counted
- gen_counter_incr(&mut asm, Counter::leave_interp_return);
+ gen_counter_incr_without_pc(&mut asm, Counter::leave_interp_return);
asm_comment!(asm, "push return value through cfp->sp");
let cfp_sp = Opnd::mem(64, CFP, RUBY_OFFSET_CFP_SP);
@@ -1257,7 +1272,7 @@ pub fn gen_single_block(
// :count-placement:
// Count bytecode instructions that execute in generated code.
// Note that the increment happens even when the output takes side exit.
- gen_counter_incr(&mut asm, Counter::yjit_insns_count);
+ gen_counter_incr(&jit, &mut asm, Counter::yjit_insns_count);
// Lookup the codegen function for this instruction
let mut status = None;
@@ -2118,13 +2133,13 @@ fn gen_expandarray(
// If this instruction has the splat flag, then bail out.
if flag & 0x01 != 0 {
- gen_counter_incr(asm, Counter::expandarray_splat);
+ gen_counter_incr(jit, asm, Counter::expandarray_splat);
return None;
}
// If this instruction has the postarg flag, then bail out.
if flag & 0x02 != 0 {
- gen_counter_incr(asm, Counter::expandarray_postarg);
+ gen_counter_incr(jit, asm, Counter::expandarray_postarg);
return None;
}
@@ -2146,7 +2161,7 @@ fn gen_expandarray(
// if to_ary is defined, return can't compile so to_ary can be called
if cme_def_type != VM_METHOD_TYPE_UNDEF {
- gen_counter_incr(asm, Counter::expandarray_to_ary);
+ gen_counter_incr(jit, asm, Counter::expandarray_to_ary);
return None;
}
@@ -2720,7 +2735,7 @@ fn gen_get_ivar(
// Use a general C call at the last chain to avoid exits on megamorphic shapes
let megamorphic = asm.ctx.get_chain_depth() >= max_chain_depth;
if megamorphic {
- gen_counter_incr(asm, Counter::num_getivar_megamorphic);
+ gen_counter_incr(jit, asm, Counter::num_getivar_megamorphic);
}
// If the class uses the default allocator, instances should all be T_OBJECT
@@ -2930,7 +2945,7 @@ fn gen_set_ivar(
// If the comptime receiver is frozen, writing an IV will raise an exception
// and we don't want to JIT code to deal with that situation.
if comptime_receiver.is_frozen() {
- gen_counter_incr(asm, Counter::setivar_frozen);
+ gen_counter_incr(jit, asm, Counter::setivar_frozen);
return None;
}
@@ -2951,7 +2966,7 @@ fn gen_set_ivar(
// Use a general C call at the last chain to avoid exits on megamorphic shapes
let megamorphic = asm.ctx.get_chain_depth() >= SET_IVAR_MAX_DEPTH;
if megamorphic {
- gen_counter_incr(asm, Counter::num_setivar_megamorphic);
+ gen_counter_incr(jit, asm, Counter::num_setivar_megamorphic);
}
// Get the iv index
@@ -3649,7 +3664,7 @@ fn gen_opt_aref(
// Only JIT one arg calls like `ary[6]`
if argc != 1 {
- gen_counter_incr(asm, Counter::opt_aref_argc_not_one);
+ gen_counter_incr(jit, asm, Counter::opt_aref_argc_not_one);
return None;
}
@@ -4396,7 +4411,7 @@ fn gen_opt_case_dispatch(
// If megamorphic, fallback to compiling branch instructions after opt_case_dispatch
let megamorphic = asm.ctx.get_chain_depth() >= CASE_WHEN_MAX_DEPTH;
if megamorphic {
- gen_counter_incr(asm, Counter::num_opt_case_dispatch_megamorphic);
+ gen_counter_incr(jit, asm, Counter::num_opt_case_dispatch_megamorphic);
}
if comptime_key.fixnum_p() && comptime_key.0 <= u32::MAX.as_usize() && case_hash_all_fixnum_p(case_hash) && !megamorphic {
@@ -4603,11 +4618,11 @@ fn gen_throw(
let throwobj = asm.load(throwobj);
// Gather some statistics about throw
- gen_counter_incr(asm, Counter::num_throw);
+ gen_counter_incr(jit, asm, Counter::num_throw);
match (throw_state & VM_THROW_STATE_MASK as u64) as u32 {
- RUBY_TAG_BREAK => gen_counter_incr(asm, Counter::num_throw_break),
- RUBY_TAG_RETRY => gen_counter_incr(asm, Counter::num_throw_retry),
- RUBY_TAG_RETURN => gen_counter_incr(asm, Counter::num_throw_return),
+ RUBY_TAG_BREAK => gen_counter_incr(jit, asm, Counter::num_throw_break),
+ RUBY_TAG_RETRY => gen_counter_incr(jit, asm, Counter::num_throw_retry),
+ RUBY_TAG_RETURN => gen_counter_incr(jit, asm, Counter::num_throw_return),
_ => {},
}
@@ -6450,11 +6465,11 @@ fn gen_send_cfunc(
// If it's a splat and the method expects a Ruby array of arguments
if cfunc_argc == -2 && flags & VM_CALL_ARGS_SPLAT != 0 {
- gen_counter_incr(asm, Counter::send_cfunc_splat_neg2);
+ gen_counter_incr(jit, asm, Counter::send_cfunc_splat_neg2);
return None;
}
- exit_if_kwsplat_non_nil(asm, flags, Counter::send_cfunc_kw_splat_non_nil)?;
+ exit_if_kwsplat_non_nil(jit, asm, flags, Counter::send_cfunc_kw_splat_non_nil)?;
let kw_splat = flags & VM_CALL_KW_SPLAT != 0;
let kw_arg = unsafe { vm_ci_kwarg(ci) };
@@ -6465,18 +6480,18 @@ fn gen_send_cfunc(
};
if kw_arg_num != 0 && flags & VM_CALL_ARGS_SPLAT != 0 {
- gen_counter_incr(asm, Counter::send_cfunc_splat_with_kw);
+ gen_counter_incr(jit, asm, Counter::send_cfunc_splat_with_kw);
return None;
}
if c_method_tracing_currently_enabled(jit) {
// Don't JIT if tracing c_call or c_return
- gen_counter_incr(asm, Counter::send_cfunc_tracing);
+ gen_counter_incr(jit, asm, Counter::send_cfunc_tracing);
return None;
}
// Increment total cfunc send count
- gen_counter_incr(asm, Counter::num_send_cfunc);
+ gen_counter_incr(jit, asm, Counter::num_send_cfunc);
// Delegate to codegen for C methods if we have it.
if kw_arg.is_null() &&
@@ -6499,7 +6514,7 @@ fn gen_send_cfunc(
if cfunc_codegen {
assert_eq!(expected_stack_after, asm.ctx.get_stack_size() as i32);
- gen_counter_incr(asm, Counter::num_send_cfunc_inline);
+ gen_counter_incr(jit, asm, Counter::num_send_cfunc_inline);
// cfunc codegen generated code. Terminate the block so
// there isn't multiple calls in the same block.
jump_to_next_insn(jit, asm);
@@ -6525,7 +6540,7 @@ fn gen_send_cfunc(
let splat_array_idx = i32::from(kw_splat) + i32::from(block_arg);
let comptime_splat_array = jit.peek_at_stack(&asm.ctx, splat_array_idx as isize);
if unsafe { rb_yjit_ruby2_keywords_splat_p(comptime_splat_array) } != 0 {
- gen_counter_incr(asm, Counter::send_cfunc_splat_varg_ruby2_keywords);
+ gen_counter_incr(jit, asm, Counter::send_cfunc_splat_varg_ruby2_keywords);
return None;
}
@@ -6554,13 +6569,13 @@ fn gen_send_cfunc(
// If the argument count doesn't match
if cfunc_argc >= 0 && cfunc_argc != passed_argc && flags & VM_CALL_ARGS_SPLAT == 0 {
- gen_counter_incr(asm, Counter::send_cfunc_argc_mismatch);
+ gen_counter_incr(jit, asm, Counter::send_cfunc_argc_mismatch);
return None;
}
// Don't JIT functions that need C stack arguments for now
if cfunc_argc >= 0 && passed_argc + 1 > (C_ARG_OPNDS.len() as i32) {
- gen_counter_incr(asm, Counter::send_cfunc_toomany_args);
+ gen_counter_incr(jit, asm, Counter::send_cfunc_toomany_args);
return None;
}
@@ -6578,7 +6593,7 @@ fn gen_send_cfunc(
// Nothing to do
}
_ => {
- gen_counter_incr(asm, Counter::send_cfunc_block_arg);
+ gen_counter_incr(jit, asm, Counter::send_cfunc_block_arg);
return None;
}
}
@@ -6614,7 +6629,7 @@ fn gen_send_cfunc(
let required_args : u32 = (cfunc_argc as u32).saturating_sub(argc as u32 - 1);
// + 1 because we pass self
if required_args + 1 >= C_ARG_OPNDS.len() as u32 {
- gen_counter_incr(asm, Counter::send_cfunc_toomany_args);
+ gen_counter_incr(jit, asm, Counter::send_cfunc_toomany_args);
return None;
}
@@ -6964,14 +6979,14 @@ fn gen_send_bmethod(
// Optimize for single ractor mode and avoid runtime check for
// "defined with an un-shareable Proc in a different Ractor"
if !assume_single_ractor_mode(jit, asm) {
- gen_counter_incr(asm, Counter::send_bmethod_ractor);
+ gen_counter_incr(jit, asm, Counter::send_bmethod_ractor);
return None;
}
// Passing a block to a block needs logic different from passing
// a block to a method and sometimes requires allocation. Bail for now.
if block.is_some() {
- gen_counter_incr(asm, Counter::send_bmethod_block_arg);
+ gen_counter_incr(jit, asm, Counter::send_bmethod_block_arg);
return None;
}
@@ -7134,29 +7149,29 @@ fn gen_send_iseq(
let splat_pos = i32::from(block_arg) + i32::from(kw_splat) + kw_arg_num;
exit_if_stack_too_large(iseq)?;
- exit_if_tail_call(asm, ci)?;
- exit_if_has_post(asm, iseq)?;
- exit_if_kwsplat_non_nil(asm, flags, Counter::send_iseq_kw_splat_non_nil)?;
- exit_if_has_rest_and_captured(asm, iseq_has_rest, captured_opnd)?;
- exit_if_has_kwrest_and_captured(asm, has_kwrest, captured_opnd)?;
- exit_if_has_rest_and_supplying_kws(asm, iseq_has_rest, supplying_kws)?;
- exit_if_supplying_kw_and_has_no_kw(asm, supplying_kws, doing_kw_call)?;
- exit_if_supplying_kws_and_accept_no_kwargs(asm, supplying_kws, iseq)?;
- exit_if_doing_kw_and_splat(asm, doing_kw_call, flags)?;
+ exit_if_tail_call(jit, asm, ci)?;
+ exit_if_has_post(jit, asm, iseq)?;
+ exit_if_kwsplat_non_nil(jit, asm, flags, Counter::send_iseq_kw_splat_non_nil)?;
+ exit_if_has_rest_and_captured(jit, asm, iseq_has_rest, captured_opnd)?;
+ exit_if_has_kwrest_and_captured(jit, asm, has_kwrest, captured_opnd)?;
+ exit_if_has_rest_and_supplying_kws(jit, asm, iseq_has_rest, supplying_kws)?;
+ exit_if_supplying_kw_and_has_no_kw(jit, asm, supplying_kws, doing_kw_call)?;
+ exit_if_supplying_kws_and_accept_no_kwargs(jit, asm, supplying_kws, iseq)?;
+ exit_if_doing_kw_and_splat(jit, asm, doing_kw_call, flags)?;
if !forwarding {
- exit_if_wrong_number_arguments(asm, arg_setup_block, opts_filled, flags, opt_num, iseq_has_rest)?;
+ exit_if_wrong_number_arguments(jit, asm, arg_setup_block, opts_filled, flags, opt_num, iseq_has_rest)?;
}
- exit_if_doing_kw_and_opts_missing(asm, doing_kw_call, opts_missing)?;
- exit_if_has_rest_and_optional_and_block(asm, iseq_has_rest, opt_num, iseq, block_arg)?;
+ exit_if_doing_kw_and_opts_missing(jit, asm, doing_kw_call, opts_missing)?;
+ exit_if_has_rest_and_optional_and_block(jit, asm, iseq_has_rest, opt_num, iseq, block_arg)?;
if forwarding && flags & VM_CALL_OPT_SEND != 0 {
- gen_counter_incr(asm, Counter::send_iseq_send_forwarding);
+ gen_counter_incr(jit, asm, Counter::send_iseq_send_forwarding);
return None;
}
let block_arg_type = exit_if_unsupported_block_arg_type(jit, asm, block_arg)?;
// Bail if we can't drop extra arguments for a yield by just popping them
if supplying_kws && arg_setup_block && argc > (kw_arg_num + required_num + opt_num) {
- gen_counter_incr(asm, Counter::send_iseq_complex_discard_extras);
+ gen_counter_incr(jit, asm, Counter::send_iseq_complex_discard_extras);
return None;
}
@@ -7168,7 +7183,7 @@ fn gen_send_iseq(
// In this case (param.flags.has_block && local_iseq != iseq),
// the block argument is setup as a local variable and requires
// materialization (allocation). Bail.
- gen_counter_incr(asm, Counter::send_iseq_materialized_block);
+ gen_counter_incr(jit, asm, Counter::send_iseq_materialized_block);
return None;
}
}
@@ -7176,7 +7191,7 @@ fn gen_send_iseq(
// Check that required keyword arguments are supplied and find any extras
// that should go into the keyword rest parameter (**kw_rest).
if doing_kw_call {
- gen_iseq_kw_call_checks(asm, iseq, kw_arg, has_kwrest, kw_arg_num)?;
+ gen_iseq_kw_call_checks(jit, asm, iseq, kw_arg, has_kwrest, kw_arg_num)?;
}
let splat_array_length = if splat_call {
@@ -7184,7 +7199,7 @@ fn gen_send_iseq(
let array_length = if array == Qnil {
0
} else if unsafe { !RB_TYPE_P(array, RUBY_T_ARRAY) } {
- gen_counter_incr(asm, Counter::send_iseq_splat_not_array);
+ gen_counter_incr(jit, asm, Counter::send_iseq_splat_not_array);
return None;
} else {
unsafe { rb_yjit_array_len(array) as u32}
@@ -7195,7 +7210,7 @@ fn gen_send_iseq(
if !iseq_has_rest {
let supplying = argc - 1 - i32::from(kw_splat) + array_length as i32;
if (required_num..=required_num + opt_num).contains(&supplying) == false {
- gen_counter_incr(asm, Counter::send_iseq_splat_arity_error);
+ gen_counter_incr(jit, asm, Counter::send_iseq_splat_arity_error);
return None;
}
}
@@ -7234,14 +7249,14 @@ fn gen_send_iseq(
// If block_arg0_splat, we still need side exits after splat, but
// the splat modifies the stack which breaks side exits. So bail out.
if splat_call {
- gen_counter_incr(asm, Counter::invokeblock_iseq_arg0_args_splat);
+ gen_counter_incr(jit, asm, Counter::invokeblock_iseq_arg0_args_splat);
return None;
}
// The block_arg0_splat implementation cannot deal with optional parameters.
// This is a setup_parameters_complex() situation and interacts with the
// starting position of the callee.
if opt_num > 1 {
- gen_counter_incr(asm, Counter::invokeblock_iseq_arg0_optional);
+ gen_counter_incr(jit, asm, Counter::invokeblock_iseq_arg0_optional);
return None;
}
}
@@ -7275,7 +7290,7 @@ fn gen_send_iseq(
}
// Increment total ISEQ send count
- gen_counter_incr(asm, Counter::num_send_iseq);
+ gen_counter_incr(jit, asm, Counter::num_send_iseq);
// Shortcut for special `Primitive.attr! :leaf` builtins
let builtin_attrs = unsafe { rb_yjit_iseq_builtin_attrs(iseq) };
@@ -7292,7 +7307,7 @@ fn gen_send_iseq(
// adding one requires interpreter changes to support.
if block_arg_type.is_some() {
if iseq_has_block_param {
- gen_counter_incr(asm, Counter::send_iseq_leaf_builtin_block_arg_block_param);
+ gen_counter_incr(jit, asm, Counter::send_iseq_leaf_builtin_block_arg_block_param);
return None;
}
asm.stack_pop(1);
@@ -7309,7 +7324,7 @@ fn gen_send_iseq(
}
asm_comment!(asm, "inlined leaf builtin");
- gen_counter_incr(asm, Counter::num_send_iseq_leaf);
+ gen_counter_incr(jit, asm, Counter::num_send_iseq_leaf);
// The callee may allocate, e.g. Integer#abs on a Bignum.
// Save SP for GC, save PC for allocation tracing, and prepare
@@ -7343,7 +7358,7 @@ fn gen_send_iseq(
// Inline simple ISEQs whose return value is known at compile time
if let (Some(value), None, false) = (iseq_get_return_value(iseq, captured_opnd, block, flags), block_arg_type, opt_send_call) {
asm_comment!(asm, "inlined simple ISEQ");
- gen_counter_incr(asm, Counter::num_send_iseq_inline);
+ gen_counter_incr(jit, asm, Counter::num_send_iseq_inline);
match value {
IseqReturn::LocalVariable(local_idx) => {
@@ -7454,7 +7469,7 @@ fn gen_send_iseq(
let callee_specval = callee_ep + VM_ENV_DATA_INDEX_SPECVAL;
if callee_specval < 0 {
// Can't write to sp[-n] since that's where the arguments are
- gen_counter_incr(asm, Counter::send_iseq_clobbering_block_arg);
+ gen_counter_incr(jit, asm, Counter::send_iseq_clobbering_block_arg);
return None;
}
let proc = asm.stack_pop(1); // Pop first, as argc doesn't account for the block arg
@@ -7480,7 +7495,7 @@ fn gen_send_iseq(
// an array that has the same length. We will insert guards.
argc = argc - 1 + array_length as i32;
if argc + asm.ctx.get_stack_size() as i32 > MAX_SPLAT_LENGTH {
- gen_counter_incr(asm, Counter::send_splat_too_long);
+ gen_counter_incr(jit, asm, Counter::send_splat_too_long);
return None;
}
push_splat_args(array_length, asm);
@@ -7853,6 +7868,7 @@ fn gen_send_iseq(
// Check if we can handle a keyword call
fn gen_iseq_kw_call_checks(
+ jit: &JITState,
asm: &mut Assembler,
iseq: *const rb_iseq_t,
kw_arg: *const rb_callinfo_kwarg,
@@ -7871,7 +7887,7 @@ fn gen_iseq_kw_call_checks(
// We have so many keywords that (1 << num) encoded as a FIXNUM
// (which shifts it left one more) no longer fits inside a 32-bit
// immediate. Similarly, we use a u64 in case of keyword rest parameter.
- gen_counter_incr(asm, Counter::send_iseq_too_many_kwargs);
+ gen_counter_incr(jit, asm, Counter::send_iseq_too_many_kwargs);
return None;
}
@@ -7912,7 +7928,7 @@ fn gen_iseq_kw_call_checks(
// If the keyword was never found, then we know we have a
// mismatch in the names of the keyword arguments, so we need to
// bail.
- gen_counter_incr(asm, Counter::send_iseq_kwargs_mismatch);
+ gen_counter_incr(jit, asm, Counter::send_iseq_kwargs_mismatch);
return None;
}
Some((callee_idx, _)) if callee_idx < keyword_required_num => {
@@ -7925,7 +7941,7 @@ fn gen_iseq_kw_call_checks(
}
assert!(required_kwargs_filled <= keyword_required_num);
if required_kwargs_filled != keyword_required_num {
- gen_counter_incr(asm, Counter::send_iseq_kwargs_mismatch);
+ gen_counter_incr(jit, asm, Counter::send_iseq_kwargs_mismatch);
return None;
}
@@ -8177,49 +8193,50 @@ fn gen_iseq_kw_call(
/// short-circuit using the ? operator if we return None.
/// It would be great if rust let you implement ? for your
/// own types, but as of right now they don't.
-fn exit_if(asm: &mut Assembler, pred: bool, counter: Counter) -> Option<()> {
+fn exit_if(jit: &JITState, asm: &mut Assembler, pred: bool, counter: Counter) -> Option<()> {
if pred {
- gen_counter_incr(asm, counter);
+ gen_counter_incr(jit, asm, counter);
return None
}
Some(())
}
#[must_use]
-fn exit_if_tail_call(asm: &mut Assembler, ci: *const rb_callinfo) -> Option<()> {
- exit_if(asm, unsafe { vm_ci_flag(ci) } & VM_CALL_TAILCALL != 0, Counter::send_iseq_tailcall)
+fn exit_if_tail_call(jit: &JITState, asm: &mut Assembler, ci: *const rb_callinfo) -> Option<()> {
+ exit_if(jit, asm, unsafe { vm_ci_flag(ci) } & VM_CALL_TAILCALL != 0, Counter::send_iseq_tailcall)
}
#[must_use]
-fn exit_if_has_post(asm: &mut Assembler, iseq: *const rb_iseq_t) -> Option<()> {
- exit_if(asm, unsafe { get_iseq_flags_has_post(iseq) }, Counter::send_iseq_has_post)
+fn exit_if_has_post(jit: &JITState, asm: &mut Assembler, iseq: *const rb_iseq_t) -> Option<()> {
+ exit_if(jit, asm, unsafe { get_iseq_flags_has_post(iseq) }, Counter::send_iseq_has_post)
}
#[must_use]
-fn exit_if_kwsplat_non_nil(asm: &mut Assembler, flags: u32, counter: Counter) -> Option<()> {
+fn exit_if_kwsplat_non_nil(jit: &JITState, asm: &mut Assembler, flags: u32, counter: Counter) -> Option<()> {
let kw_splat = flags & VM_CALL_KW_SPLAT != 0;
let kw_splat_stack = StackOpnd((flags & VM_CALL_ARGS_BLOCKARG != 0).into());
- exit_if(asm, kw_splat && asm.ctx.get_opnd_type(kw_splat_stack) != Type::Nil, counter)
+ exit_if(jit, asm, kw_splat && asm.ctx.get_opnd_type(kw_splat_stack) != Type::Nil, counter)
}
#[must_use]
-fn exit_if_has_rest_and_captured(asm: &mut Assembler, iseq_has_rest: bool, captured_opnd: Option<Opnd>) -> Option<()> {
- exit_if(asm, iseq_has_rest && captured_opnd.is_some(), Counter::send_iseq_has_rest_and_captured)
+fn exit_if_has_rest_and_captured(jit: &JITState, asm: &mut Assembler, iseq_has_rest: bool, captured_opnd: Option<Opnd>) -> Option<()> {
+ exit_if(jit, asm, iseq_has_rest && captured_opnd.is_some(), Counter::send_iseq_has_rest_and_captured)
}
#[must_use]
-fn exit_if_has_kwrest_and_captured(asm: &mut Assembler, iseq_has_kwrest: bool, captured_opnd: Option<Opnd>) -> Option<()> {
+fn exit_if_has_kwrest_and_captured(jit: &JITState, asm: &mut Assembler, iseq_has_kwrest: bool, captured_opnd: Option<Opnd>) -> Option<()> {
// We need to call a C function to allocate the kwrest hash, but also need to hold the captred
// block across the call, which we can't do.
- exit_if(asm, iseq_has_kwrest && captured_opnd.is_some(), Counter::send_iseq_has_kwrest_and_captured)
+ exit_if(jit, asm, iseq_has_kwrest && captured_opnd.is_some(), Counter::send_iseq_has_kwrest_and_captured)
}
#[must_use]
-fn exit_if_has_rest_and_supplying_kws(asm: &mut Assembler, iseq_has_rest: bool, supplying_kws: bool) -> Option<()> {
+fn exit_if_has_rest_and_supplying_kws(jit: &JITState, asm: &mut Assembler, iseq_has_rest: bool, supplying_kws: bool) -> Option<()> {
// There can be a gap between the rest parameter array and the supplied keywords, or
// no space to put the rest array (e.g. `def foo(*arr, k:) = arr; foo(k: 1)` 1 is
// sitting where the rest array should be).
exit_if(
+ jit,
asm,
iseq_has_rest && supplying_kws,
Counter::send_iseq_has_rest_and_kw_supplied,
@@ -8227,10 +8244,11 @@ fn exit_if_has_rest_and_supplying_kws(asm: &mut Assembler, iseq_has_rest: bool,
}
#[must_use]
-fn exit_if_supplying_kw_and_has_no_kw(asm: &mut Assembler, supplying_kws: bool, callee_kws: bool) -> Option<()> {
+fn exit_if_supplying_kw_and_has_no_kw(jit: &JITState, asm: &mut Assembler, supplying_kws: bool, callee_kws: bool) -> Option<()> {
// Passing keyword arguments to a callee means allocating a hash and treating
// that as a positional argument. Bail for now.
exit_if(
+ jit,
asm,
supplying_kws && !callee_kws,
Counter::send_iseq_has_no_kw,
@@ -8238,10 +8256,11 @@ fn exit_if_supplying_kw_and_has_no_kw(asm: &mut Assembler, supplying_kws: bool,
}
#[must_use]
-fn exit_if_supplying_kws_and_accept_no_kwargs(asm: &mut Assembler, supplying_kws: bool, iseq: *const rb_iseq_t) -> Option<()> {
+fn exit_if_supplying_kws_and_accept_no_kwargs(jit: &JITState, asm: &mut Assembler, supplying_kws: bool, iseq: *const rb_iseq_t) -> Option<()> {
// If we have a method accepting no kwargs (**nil), exit if we have passed
// it any kwargs.
exit_if(
+ jit,
asm,
supplying_kws && unsafe { get_iseq_flags_accepts_no_kwarg(iseq) },
Counter::send_iseq_accepts_no_kwarg
@@ -8249,12 +8268,13 @@ fn exit_if_supplying_kws_and_accept_no_kwargs(asm: &mut Assembler, supplying_kws
}
#[must_use]
-fn exit_if_doing_kw_and_splat(asm: &mut Assembler, doing_kw_call: bool, flags: u32) -> Option<()> {
- exit_if(asm, doing_kw_call && flags & VM_CALL_ARGS_SPLAT != 0, Counter::send_iseq_splat_with_kw)
+fn exit_if_doing_kw_and_splat(jit: &JITState, asm: &mut Assembler, doing_kw_call: bool, flags: u32) -> Option<()> {
+ exit_if(jit, asm, doing_kw_call && flags & VM_CALL_ARGS_SPLAT != 0, Counter::send_iseq_splat_with_kw)
}
#[must_use]
fn exit_if_wrong_number_arguments(
+ jit: &JITState,
asm: &mut Assembler,
args_setup_block: bool,
opts_filled: i32,
@@ -8267,20 +8287,21 @@ fn exit_if_wrong_number_arguments(
// Too many arguments and no sink that take them
let too_many = opts_filled > opt_num && !(iseq_has_rest || args_setup_block);
- exit_if(asm, too_few || too_many, Counter::send_iseq_arity_error)
+ exit_if(jit, asm, too_few || too_many, Counter::send_iseq_arity_error)
}
#[must_use]
-fn exit_if_doing_kw_and_opts_missing(asm: &mut Assembler, doing_kw_call: bool, opts_missing: i32) -> Option<()> {
+fn exit_if_doing_kw_and_opts_missing(jit: &JITState, asm: &mut Assembler, doing_kw_call: bool, opts_missing: i32) -> Option<()> {
// If we have unfilled optional arguments and keyword arguments then we
// would need to adjust the arguments location to account for that.
// For now we aren't handling this case.
- exit_if(asm, doing_kw_call && opts_missing > 0, Counter::send_iseq_missing_optional_kw)
+ exit_if(jit, asm, doing_kw_call && opts_missing > 0, Counter::send_iseq_missing_optional_kw)
}
#[must_use]
-fn exit_if_has_rest_and_optional_and_block(asm: &mut Assembler, iseq_has_rest: bool, opt_num: i32, iseq: *const rb_iseq_t, block_arg: bool) -> Option<()> {
+fn exit_if_has_rest_and_optional_and_block(jit: &JITState, asm: &mut Assembler, iseq_has_rest: bool, opt_num: i32, iseq: *const rb_iseq_t, block_arg: bool) -> Option<()> {
exit_if(
+ jit,
asm,
iseq_has_rest && opt_num != 0 && (unsafe { get_iseq_flags_has_block(iseq) } || block_arg),
Counter::send_iseq_has_rest_opt_and_block
@@ -8322,7 +8343,7 @@ fn exit_if_unsupported_block_arg_type(
Some(Some(BlockArg::TProc))
}
_ => {
- gen_counter_incr(asm, Counter::send_iseq_block_arg_type);
+ gen_counter_incr(jit, asm, Counter::send_iseq_block_arg_type);
None
}
}
@@ -8374,7 +8395,7 @@ fn gen_struct_aref(
if c_method_tracing_currently_enabled(jit) {
// Struct accesses need fire c_call and c_return events, which we can't support
// See :attr-tracing:
- gen_counter_incr(asm, Counter::send_cfunc_tracing);
+ gen_counter_incr(jit, asm, Counter::send_cfunc_tracing);
return None;
}
@@ -8424,7 +8445,7 @@ fn gen_struct_aset(
if c_method_tracing_currently_enabled(jit) {
// Struct accesses need fire c_call and c_return events, which we can't support
// See :attr-tracing:
- gen_counter_incr(asm, Counter::send_cfunc_tracing);
+ gen_counter_incr(jit, asm, Counter::send_cfunc_tracing);
return None;
}
@@ -8489,7 +8510,7 @@ fn gen_send_dynamic<F: Fn(&mut Assembler) -> Opnd>(
// Fix the interpreter SP deviated by vm_sendish
asm.mov(Opnd::mem(64, CFP, RUBY_OFFSET_CFP_SP), SP);
- gen_counter_incr(asm, Counter::num_send_dynamic);
+ gen_counter_incr(jit, asm, Counter::num_send_dynamic);
jit_perf_symbol_pop!(jit, asm, PerfMap::Codegen);
@@ -8529,7 +8550,7 @@ fn gen_send_general(
// Dynamic stack layout. No good way to support without inlining.
if ci_flags & VM_CALL_FORWARDING != 0 {
- gen_counter_incr(asm, Counter::send_iseq_forwarding);
+ gen_counter_incr(jit, asm, Counter::send_iseq_forwarding);
return None;
}
@@ -8546,7 +8567,7 @@ fn gen_send_general(
&& comptime_recv != unsafe { rb_vm_top_self() }
&& !unsafe { RB_TYPE_P(comptime_recv, RUBY_T_CLASS) }
&& !unsafe { RB_TYPE_P(comptime_recv, RUBY_T_MODULE) } {
- gen_counter_incr(asm, Counter::send_singleton_class);
+ gen_counter_incr(jit, asm, Counter::send_singleton_class);
return None;
}
@@ -8559,16 +8580,16 @@ fn gen_send_general(
asm_comment!(asm, "call to {}", get_method_name(Some(comptime_recv_klass), mid));
// Gather some statistics about sends
- gen_counter_incr(asm, Counter::num_send);
+ gen_counter_incr(jit, asm, Counter::num_send);
if let Some(_known_klass) = asm.ctx.get_opnd_type(recv_opnd).known_class() {
- gen_counter_incr(asm, Counter::num_send_known_class);
+ gen_counter_incr(jit, asm, Counter::num_send_known_class);
}
if asm.ctx.get_chain_depth() > 1 {
- gen_counter_incr(asm, Counter::num_send_polymorphic);
+ gen_counter_incr(jit, asm, Counter::num_send_polymorphic);
}
// If megamorphic, let the caller fallback to dynamic dispatch
if asm.ctx.get_chain_depth() >= SEND_MAX_DEPTH {
- gen_counter_incr(asm, Counter::send_megamorphic);
+ gen_counter_incr(jit, asm, Counter::send_megamorphic);
return None;
}
@@ -8586,7 +8607,7 @@ fn gen_send_general(
// Do method lookup
let mut cme = unsafe { rb_callable_method_entry(comptime_recv_klass, mid) };
if cme.is_null() {
- gen_counter_incr(asm, Counter::send_cme_not_found);
+ gen_counter_incr(jit, asm, Counter::send_cme_not_found);
return None;
}
@@ -8603,7 +8624,7 @@ fn gen_send_general(
if flags & VM_CALL_FCALL == 0 {
// Can only call private methods with FCALL callsites.
// (at the moment they are callsites without a receiver or an explicit `self` receiver)
- gen_counter_incr(asm, Counter::send_private_not_fcall);
+ gen_counter_incr(jit, asm, Counter::send_private_not_fcall);
return None;
}
}
@@ -8649,7 +8670,7 @@ fn gen_send_general(
VM_METHOD_TYPE_IVAR => {
// This is a .send call not supported right now for attr_reader
if flags & VM_CALL_OPT_SEND != 0 {
- gen_counter_incr(asm, Counter::send_send_attr_reader);
+ gen_counter_incr(jit, asm, Counter::send_send_attr_reader);
return None;
}
@@ -8661,7 +8682,7 @@ fn gen_send_general(
asm.stack_pop(1);
}
_ => {
- gen_counter_incr(asm, Counter::send_getter_block_arg);
+ gen_counter_incr(jit, asm, Counter::send_getter_block_arg);
return None;
}
}
@@ -8681,7 +8702,7 @@ fn gen_send_general(
asm.stack_pop(1);
} else {
// Argument count mismatch. Getters take no arguments.
- gen_counter_incr(asm, Counter::send_getter_arity);
+ gen_counter_incr(jit, asm, Counter::send_getter_arity);
return None;
}
}
@@ -8694,7 +8715,7 @@ fn gen_send_general(
// "method" we are calling into never enables those tracing
// events. We are never inside the code that needs to be
// invalidated when invalidation happens.
- gen_counter_incr(asm, Counter::send_cfunc_tracing);
+ gen_counter_incr(jit, asm, Counter::send_cfunc_tracing);
return None;
}
@@ -8714,26 +8735,26 @@ fn gen_send_general(
VM_METHOD_TYPE_ATTRSET => {
// This is a .send call not supported right now for attr_writer
if flags & VM_CALL_OPT_SEND != 0 {
- gen_counter_incr(asm, Counter::send_send_attr_writer);
+ gen_counter_incr(jit, asm, Counter::send_send_attr_writer);
return None;
}
if flags & VM_CALL_ARGS_SPLAT != 0 {
- gen_counter_incr(asm, Counter::send_args_splat_attrset);
+ gen_counter_incr(jit, asm, Counter::send_args_splat_attrset);
return None;
}
if flags & VM_CALL_KWARG != 0 {
- gen_counter_incr(asm, Counter::send_attrset_kwargs);
+ gen_counter_incr(jit, asm, Counter::send_attrset_kwargs);
return None;
} else if argc != 1 || unsafe { !RB_TYPE_P(comptime_recv, RUBY_T_OBJECT) } {
- gen_counter_incr(asm, Counter::send_ivar_set_method);
+ gen_counter_incr(jit, asm, Counter::send_ivar_set_method);
return None;
} else if c_method_tracing_currently_enabled(jit) {
// Can't generate code for firing c_call and c_return events
// See :attr-tracing:
- gen_counter_incr(asm, Counter::send_cfunc_tracing);
+ gen_counter_incr(jit, asm, Counter::send_cfunc_tracing);
return None;
} else if flags & VM_CALL_ARGS_BLOCKARG != 0 {
- gen_counter_incr(asm, Counter::send_attrset_block_arg);
+ gen_counter_incr(jit, asm, Counter::send_attrset_block_arg);
return None;
} else {
let ivar_name = unsafe { get_cme_def_body_attr_id(cme) };
@@ -8743,7 +8764,7 @@ fn gen_send_general(
// Block method, e.g. define_method(:foo) { :my_block }
VM_METHOD_TYPE_BMETHOD => {
if flags & VM_CALL_ARGS_SPLAT != 0 {
- gen_counter_incr(asm, Counter::send_args_splat_bmethod);
+ gen_counter_incr(jit, asm, Counter::send_args_splat_bmethod);
return None;
}
return gen_send_bmethod(jit, asm, ci, cme, block, flags, argc);
@@ -8756,7 +8777,7 @@ fn gen_send_general(
// Send family of methods, e.g. call/apply
VM_METHOD_TYPE_OPTIMIZED => {
if flags & VM_CALL_ARGS_BLOCKARG != 0 {
- gen_counter_incr(asm, Counter::send_optimized_block_arg);
+ gen_counter_incr(jit, asm, Counter::send_optimized_block_arg);
return None;
}
@@ -8774,12 +8795,12 @@ fn gen_send_general(
// currently work, we can't do stack manipulation until we will no longer
// side exit.
if flags & VM_CALL_OPT_SEND != 0 {
- gen_counter_incr(asm, Counter::send_send_nested);
+ gen_counter_incr(jit, asm, Counter::send_send_nested);
return None;
}
if argc == 0 {
- gen_counter_incr(asm, Counter::send_send_wrong_args);
+ gen_counter_incr(jit, asm, Counter::send_send_wrong_args);
return None;
}
@@ -8790,13 +8811,13 @@ fn gen_send_general(
mid = unsafe { rb_get_symbol_id(compile_time_name) };
if mid == 0 {
// This also rejects method names that need conversion
- gen_counter_incr(asm, Counter::send_send_null_mid);
+ gen_counter_incr(jit, asm, Counter::send_send_null_mid);
return None;
}
cme = unsafe { rb_callable_method_entry(comptime_recv_klass, mid) };
if cme.is_null() {
- gen_counter_incr(asm, Counter::send_send_null_cme);
+ gen_counter_incr(jit, asm, Counter::send_send_null_cme);
return None;
}
@@ -8830,24 +8851,24 @@ fn gen_send_general(
OPTIMIZED_METHOD_TYPE_CALL => {
if block.is_some() {
- gen_counter_incr(asm, Counter::send_call_block);
+ gen_counter_incr(jit, asm, Counter::send_call_block);
return None;
}
if flags & VM_CALL_KWARG != 0 {
- gen_counter_incr(asm, Counter::send_call_kwarg);
+ gen_counter_incr(jit, asm, Counter::send_call_kwarg);
return None;
}
if flags & VM_CALL_ARGS_SPLAT != 0 {
- gen_counter_incr(asm, Counter::send_args_splat_opt_call);
+ gen_counter_incr(jit, asm, Counter::send_args_splat_opt_call);
return None;
}
// Optimize for single ractor mode and avoid runtime check for
// "defined with an un-shareable Proc in a different Ractor"
if !assume_single_ractor_mode(jit, asm) {
- gen_counter_incr(asm, Counter::send_call_multi_ractor);
+ gen_counter_incr(jit, asm, Counter::send_call_multi_ractor);
return None;
}
@@ -8884,12 +8905,12 @@ fn gen_send_general(
}
OPTIMIZED_METHOD_TYPE_BLOCK_CALL => {
- gen_counter_incr(asm, Counter::send_optimized_method_block_call);
+ gen_counter_incr(jit, asm, Counter::send_optimized_method_block_call);
return None;
}
OPTIMIZED_METHOD_TYPE_STRUCT_AREF => {
if flags & VM_CALL_ARGS_SPLAT != 0 {
- gen_counter_incr(asm, Counter::send_args_splat_aref);
+ gen_counter_incr(jit, asm, Counter::send_args_splat_aref);
return None;
}
return gen_struct_aref(
@@ -8904,7 +8925,7 @@ fn gen_send_general(
}
OPTIMIZED_METHOD_TYPE_STRUCT_ASET => {
if flags & VM_CALL_ARGS_SPLAT != 0 {
- gen_counter_incr(asm, Counter::send_args_splat_aset);
+ gen_counter_incr(jit, asm, Counter::send_args_splat_aset);
return None;
}
return gen_struct_aset(
@@ -8923,23 +8944,23 @@ fn gen_send_general(
}
}
VM_METHOD_TYPE_ZSUPER => {
- gen_counter_incr(asm, Counter::send_zsuper_method);
+ gen_counter_incr(jit, asm, Counter::send_zsuper_method);
return None;
}
VM_METHOD_TYPE_UNDEF => {
- gen_counter_incr(asm, Counter::send_undef_method);
+ gen_counter_incr(jit, asm, Counter::send_undef_method);
return None;
}
VM_METHOD_TYPE_NOTIMPLEMENTED => {
- gen_counter_incr(asm, Counter::send_not_implemented_method);
+ gen_counter_incr(jit, asm, Counter::send_not_implemented_method);
return None;
}
VM_METHOD_TYPE_MISSING => {
- gen_counter_incr(asm, Counter::send_missing_method);
+ gen_counter_incr(jit, asm, Counter::send_missing_method);
return None;
}
VM_METHOD_TYPE_REFINED => {
- gen_counter_incr(asm, Counter::send_refined_method);
+ gen_counter_incr(jit, asm, Counter::send_refined_method);
return None;
}
_ => {
@@ -9088,7 +9109,7 @@ fn gen_invokeblock_specialized(
// Fallback to dynamic dispatch if this callsite is megamorphic
if asm.ctx.get_chain_depth() >= SEND_MAX_DEPTH {
- gen_counter_incr(asm, Counter::invokeblock_megamorphic);
+ gen_counter_incr(jit, asm, Counter::invokeblock_megamorphic);
return None;
}
@@ -9104,7 +9125,7 @@ fn gen_invokeblock_specialized(
// Handle each block_handler type
if comptime_handler.0 == VM_BLOCK_HANDLER_NONE as usize { // no block given
- gen_counter_incr(asm, Counter::invokeblock_none);
+ gen_counter_incr(jit, asm, Counter::invokeblock_none);
None
} else if comptime_handler.0 & 0x3 == 0x1 { // VM_BH_ISEQ_BLOCK_P
asm_comment!(asm, "get local EP");
@@ -9127,7 +9148,7 @@ fn gen_invokeblock_specialized(
// If the current ISEQ is annotated to be inlined but it's not being inlined here,
// generate a dynamic dispatch to avoid making this yield megamorphic.
if unsafe { rb_yjit_iseq_builtin_attrs(jit.iseq) } & BUILTIN_ATTR_INLINE_BLOCK != 0 && !asm.ctx.inline() {
- gen_counter_incr(asm, Counter::invokeblock_iseq_not_inlined);
+ gen_counter_incr(jit, asm, Counter::invokeblock_iseq_not_inlined);
return None;
}
@@ -9150,11 +9171,11 @@ fn gen_invokeblock_specialized(
} else if comptime_handler.0 & 0x3 == 0x3 { // VM_BH_IFUNC_P
// We aren't handling CALLER_SETUP_ARG and CALLER_REMOVE_EMPTY_KW_SPLAT yet.
if flags & VM_CALL_ARGS_SPLAT != 0 {
- gen_counter_incr(asm, Counter::invokeblock_ifunc_args_splat);
+ gen_counter_incr(jit, asm, Counter::invokeblock_ifunc_args_splat);
return None;
}
if flags & VM_CALL_KW_SPLAT != 0 {
- gen_counter_incr(asm, Counter::invokeblock_ifunc_kw_splat);
+ gen_counter_incr(jit, asm, Counter::invokeblock_ifunc_kw_splat);
return None;
}
@@ -9200,10 +9221,10 @@ fn gen_invokeblock_specialized(
jump_to_next_insn(jit, asm);
Some(EndBlock)
} else if comptime_handler.symbol_p() {
- gen_counter_incr(asm, Counter::invokeblock_symbol);
+ gen_counter_incr(jit, asm, Counter::invokeblock_symbol);
None
} else { // Proc
- gen_counter_incr(asm, Counter::invokeblock_proc);
+ gen_counter_incr(jit, asm, Counter::invokeblock_proc);
None
}
}
@@ -9258,13 +9279,13 @@ fn gen_invokesuper_specialized(
// Fallback to dynamic dispatch if this callsite is megamorphic
if asm.ctx.get_chain_depth() >= SEND_MAX_DEPTH {
- gen_counter_incr(asm, Counter::invokesuper_megamorphic);
+ gen_counter_incr(jit, asm, Counter::invokesuper_megamorphic);
return None;
}
let me = unsafe { rb_vm_frame_method_entry(jit.get_cfp()) };
if me.is_null() {
- gen_counter_incr(asm, Counter::invokesuper_no_me);
+ gen_counter_incr(jit, asm, Counter::invokesuper_no_me);
return None;
}
@@ -9277,7 +9298,7 @@ fn gen_invokesuper_specialized(
if current_defined_class.builtin_type() == RUBY_T_ICLASS
&& unsafe { RB_TYPE_P((*rbasic_ptr).klass, RUBY_T_MODULE) && FL_TEST_RAW((*rbasic_ptr).klass, VALUE(RMODULE_IS_REFINEMENT.as_usize())) != VALUE(0) }
{
- gen_counter_incr(asm, Counter::invokesuper_refinement);
+ gen_counter_incr(jit, asm, Counter::invokesuper_refinement);
return None;
}
let comptime_superclass =
@@ -9292,15 +9313,15 @@ fn gen_invokesuper_specialized(
// Note, not using VM_CALL_ARGS_SIMPLE because sometimes we pass a block.
if ci_flags & VM_CALL_KWARG != 0 {
- gen_counter_incr(asm, Counter::invokesuper_kwarg);
+ gen_counter_incr(jit, asm, Counter::invokesuper_kwarg);
return None;
}
if ci_flags & VM_CALL_KW_SPLAT != 0 {
- gen_counter_incr(asm, Counter::invokesuper_kw_splat);
+ gen_counter_incr(jit, asm, Counter::invokesuper_kw_splat);
return None;
}
if ci_flags & VM_CALL_FORWARDING != 0 {
- gen_counter_incr(asm, Counter::invokesuper_forwarding);
+ gen_counter_incr(jit, asm, Counter::invokesuper_forwarding);
return None;
}
@@ -9311,20 +9332,20 @@ fn gen_invokesuper_specialized(
// check and side exit.
let comptime_recv = jit.peek_at_stack(&asm.ctx, argc as isize);
if unsafe { rb_obj_is_kind_of(comptime_recv, current_defined_class) } == VALUE(0) {
- gen_counter_incr(asm, Counter::invokesuper_defined_class_mismatch);
+ gen_counter_incr(jit, asm, Counter::invokesuper_defined_class_mismatch);
return None;
}
// Don't compile `super` on objects with singleton class to avoid retaining the receiver.
if VALUE(0) != unsafe { FL_TEST(comptime_recv.class_of(), VALUE(RUBY_FL_SINGLETON as usize)) } {
- gen_counter_incr(asm, Counter::invokesuper_singleton_class);
+ gen_counter_incr(jit, asm, Counter::invokesuper_singleton_class);
return None;
}
// Do method lookup
let cme = unsafe { rb_callable_method_entry(comptime_superclass, mid) };
if cme.is_null() {
- gen_counter_incr(asm, Counter::invokesuper_no_cme);
+ gen_counter_incr(jit, asm, Counter::invokesuper_no_cme);
return None;
}
@@ -9332,7 +9353,7 @@ fn gen_invokesuper_specialized(
let cme_def_type = unsafe { get_cme_def_type(cme) };
if cme_def_type != VM_METHOD_TYPE_ISEQ && cme_def_type != VM_METHOD_TYPE_CFUNC {
// others unimplemented
- gen_counter_incr(asm, Counter::invokesuper_not_iseq_or_cfunc);
+ gen_counter_incr(jit, asm, Counter::invokesuper_not_iseq_or_cfunc);
return None;
}
@@ -9799,7 +9820,7 @@ fn gen_opt_getconstant_path(
} else {
// Optimize for single ractor mode.
if !assume_single_ractor_mode(jit, asm) {
- gen_counter_incr(asm, Counter::opt_getconstant_path_multi_ractor);
+ gen_counter_incr(jit, asm, Counter::opt_getconstant_path_multi_ractor);
return None;
}
@@ -9839,7 +9860,7 @@ fn gen_getblockparamproxy(
unsafe { rb_obj_is_proc(comptime_handler) }.test() // block is a Proc
) {
// Missing the symbol case, where we basically need to call Symbol#to_proc at runtime
- gen_counter_incr(asm, Counter::gbpp_unsupported_type);
+ gen_counter_incr(jit, asm, Counter::gbpp_unsupported_type);
return None;
}
diff --git a/yjit/src/options.rs b/yjit/src/options.rs
index 3882c8a786..85d068595a 100644
--- a/yjit/src/options.rs
+++ b/yjit/src/options.rs
@@ -116,8 +116,8 @@ static YJIT_OPTIONS: [(&str, &str); 9] = [
pub enum TraceExits {
// Trace all exits
All,
- // Trace a specific counted exit
- CountedExit(Counter),
+ // Trace a specific counter
+ Counter(Counter),
}
#[derive(Debug)]
@@ -293,7 +293,7 @@ pub fn parse_option(str_ptr: *const std::os::raw::c_char) -> Option<()> {
OPTIONS.trace_exits = match opt_val {
"" => Some(TraceExits::All),
name => match Counter::get(name) {
- Some(counter) => Some(TraceExits::CountedExit(counter)),
+ Some(counter) => Some(TraceExits::Counter(counter)),
None => return None,
},
};