summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <[email protected]>2023-08-02 07:19:39 -0700
committerGitHub <[email protected]>2023-08-02 10:19:39 -0400
commit81c198b5cfced7f9e8205e726bf686763370ce18 (patch)
tree9c4565bb102bf2791fd2f50939af0dc00171d1f1
parent452debba22cfae0ed61042afb21f2bf86135c1dc (diff)
YJIT: Distinguish exit and fallback reasons for send (#8159)
Notes
Notes: Merged-By: maximecb <[email protected]>
-rw-r--r--yjit.rb3
-rw-r--r--yjit/src/codegen.rs42
-rw-r--r--yjit/src/stats.rs36
3 files changed, 42 insertions, 39 deletions
diff --git a/yjit.rb b/yjit.rb
index 59e048cd0e..c512021bb4 100644
--- a/yjit.rb
+++ b/yjit.rb
@@ -250,7 +250,8 @@ module RubyVM::YJIT
out.puts("***YJIT: Printing YJIT statistics on exit***")
- print_counters(stats, out: out, prefix: 'send_', prompt: 'method call exit reasons: ')
+ print_counters(stats, out: out, prefix: 'send_', prompt: 'method call fallback reasons: ')
+ print_counters(stats, out: out, prefix: 'guard_send_', prompt: 'method call exit reasons: ')
print_counters(stats, out: out, prefix: 'invokeblock_', prompt: 'invokeblock exit reasons: ')
print_counters(stats, out: out, prefix: 'invokesuper_', prompt: 'invokesuper exit reasons: ')
print_counters(stats, out: out, prefix: 'leave_', prompt: 'leave exit reasons: ')
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index daf898c3cd..6b4c67d31e 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -2574,7 +2574,7 @@ fn guard_two_fixnums(
asm: &mut Assembler,
ocb: &mut OutlinedCb,
) {
- let counter = Counter::send_not_fixnums;
+ let counter = Counter::guard_send_not_fixnums;
// Get stack operands without popping them
let arg1 = asm.stack_opnd(0);
@@ -2779,7 +2779,7 @@ fn gen_equality_specialized(
a_opnd.into(),
comptime_a,
SEND_MAX_DEPTH,
- Counter::send_not_string,
+ Counter::guard_send_not_string,
);
let equal = asm.new_label("equal");
@@ -2806,7 +2806,7 @@ fn gen_equality_specialized(
b_opnd.into(),
comptime_b,
SEND_MAX_DEPTH,
- Counter::send_not_string,
+ Counter::guard_send_not_string,
);
}
@@ -3994,7 +3994,7 @@ fn jit_protected_callee_ancestry_guard(
],
);
asm.test(val, val);
- asm.jz(Target::side_exit(Counter::send_se_protected_check_failed))
+ asm.jz(Target::side_exit(Counter::guard_send_se_protected_check_failed))
}
// Codegen for rb_obj_not().
@@ -4109,7 +4109,7 @@ fn jit_rb_kernel_is_a(
asm.comment("Kernel#is_a?");
asm.cmp(asm.stack_opnd(0), sample_rhs.into());
- asm.jne(Target::side_exit(Counter::send_is_a_class_mismatch));
+ asm.jne(Target::side_exit(Counter::guard_send_is_a_class_mismatch));
asm.stack_pop(2);
@@ -4168,7 +4168,7 @@ fn jit_rb_kernel_instance_of(
asm.comment("Kernel#instance_of?");
asm.cmp(asm.stack_opnd(0), sample_rhs.into());
- asm.jne(Target::side_exit(Counter::send_instance_of_class_mismatch));
+ asm.jne(Target::side_exit(Counter::guard_send_instance_of_class_mismatch));
asm.stack_pop(2);
@@ -4544,7 +4544,7 @@ fn jit_rb_str_concat(
}
// Guard that the concat argument is a string
- guard_object_is_string(asm, asm.stack_opnd(0), StackOpnd(0), Counter::send_not_string);
+ guard_object_is_string(asm, asm.stack_opnd(0), StackOpnd(0), Counter::guard_send_not_string);
// Guard buffers from GC since rb_str_buf_append may allocate. During the VM lock on GC,
// other Ractors may trigger global invalidation, so we need ctx.clear_local_types().
@@ -4727,7 +4727,7 @@ fn jit_obj_respond_to(
// This is necessary because we have no guarantee that sym_opnd is a constant
asm.comment("guard known mid");
asm.cmp(sym_opnd, mid_sym.into());
- asm.jne(Target::side_exit(Counter::send_mid_mismatch));
+ asm.jne(Target::side_exit(Counter::guard_send_mid_mismatch));
jit_putobject(asm, result);
@@ -5070,7 +5070,7 @@ fn gen_send_cfunc(
}
// Check for interrupts
- gen_check_ints(asm, Counter::send_interrupted);
+ gen_check_ints(asm, Counter::guard_send_interrupted);
// Stack overflow check
// #define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin)
@@ -5078,7 +5078,7 @@ fn gen_send_cfunc(
asm.comment("stack overflow check");
let stack_limit = asm.lea(asm.ctx.sp_opnd((SIZEOF_VALUE * 4 + 2 * RUBY_SIZEOF_CONTROL_FRAME) as isize));
asm.cmp(CFP, stack_limit);
- asm.jbe(Target::side_exit(Counter::send_se_cf_overflow));
+ asm.jbe(Target::side_exit(Counter::guard_send_se_cf_overflow));
// Number of args which will be passed through to the callee
// This is adjusted by the kwargs being combined into a hash.
@@ -5339,7 +5339,7 @@ fn move_rest_args_to_stack(array: Opnd, num_args: u32, asm: &mut Assembler) {
asm.comment("Side exit if length is less than required");
asm.cmp(array_len_opnd, num_args.into());
- asm.jl(Target::side_exit(Counter::send_iseq_has_rest_and_splat_not_equal));
+ asm.jl(Target::side_exit(Counter::guard_send_iseq_has_rest_and_splat_not_equal));
asm.comment("Push arguments from array");
@@ -5380,7 +5380,7 @@ fn push_splat_args(required_args: u32, asm: &mut Assembler) {
asm,
array_reg,
array_opnd.into(),
- Counter::send_splat_not_array,
+ Counter::guard_send_splat_not_array,
);
asm.comment("Get array length for embedded or heap");
@@ -5409,7 +5409,7 @@ fn push_splat_args(required_args: u32, asm: &mut Assembler) {
asm.comment("Side exit if length doesn't not equal remaining args");
asm.cmp(array_len_opnd, required_args.into());
- asm.jne(Target::side_exit(Counter::send_splatarray_length_not_equal));
+ asm.jne(Target::side_exit(Counter::guard_send_splatarray_length_not_equal));
asm.comment("Check last argument is not ruby2keyword hash");
@@ -5423,7 +5423,7 @@ fn push_splat_args(required_args: u32, asm: &mut Assembler) {
guard_object_is_not_ruby2_keyword_hash(
asm,
last_array_value,
- Counter::send_splatarray_last_ruby_2_keywords,
+ Counter::guard_send_splatarray_last_ruby_2_keywords,
);
asm.comment("Push arguments from array");
@@ -5720,7 +5720,7 @@ fn gen_send_iseq(
asm.comment("Side exit if length doesn't not equal compile time length");
let array_len_opnd = get_array_len(asm, asm.stack_opnd(if block_arg { 1 } else { 0 }));
asm.cmp(array_len_opnd, array_length.into());
- asm.jne(Target::side_exit(Counter::send_splatarray_length_not_equal));
+ asm.jne(Target::side_exit(Counter::guard_send_splatarray_length_not_equal));
}
Some(array_length)
@@ -5834,7 +5834,7 @@ fn gen_send_iseq(
SIZEOF_VALUE_I32 * (num_locals + stack_max) + 2 * (RUBY_SIZEOF_CONTROL_FRAME as i32);
let stack_limit = asm.lea(asm.ctx.sp_opnd(locals_offs as isize));
asm.cmp(CFP, stack_limit);
- asm.jbe(Target::side_exit(Counter::send_se_cf_overflow));
+ asm.jbe(Target::side_exit(Counter::guard_send_se_cf_overflow));
// push_splat_args does stack manipulation so we can no longer side exit
if let Some(array_length) = splat_array_length {
@@ -6626,7 +6626,7 @@ fn gen_send_general(
recv_opnd,
comptime_recv,
SEND_MAX_DEPTH,
- Counter::send_klass_megamorphic,
+ Counter::guard_send_klass_megamorphic,
);
// Do method lookup
@@ -6834,12 +6834,12 @@ fn gen_send_general(
if compile_time_name.string_p() {
(
unsafe { rb_cString },
- Counter::send_send_chain_not_string,
+ Counter::guard_send_send_chain_not_string,
)
} else {
(
unsafe { rb_cSymbol },
- Counter::send_send_chain_not_sym,
+ Counter::guard_send_send_chain_not_sym,
)
}
};
@@ -6871,7 +6871,7 @@ fn gen_send_general(
asm,
ocb,
SEND_MAX_CHAIN_DEPTH,
- Counter::send_send_chain,
+ Counter::guard_send_send_chain,
);
// We have changed the argc, flags, mid, and cme, so we need to re-enter the match
@@ -8575,7 +8575,7 @@ mod tests {
fn test_gen_check_ints() {
let (_jit, _ctx, mut asm, _cb, _ocb) = setup_codegen();
asm.set_side_exit_context(0 as _, 0);
- gen_check_ints(&mut asm, Counter::send_interrupted);
+ gen_check_ints(&mut asm, Counter::guard_send_interrupted);
}
#[test]
diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs
index b1773df359..686516cb9b 100644
--- a/yjit/src/stats.rs
+++ b/yjit/src/stats.rs
@@ -204,8 +204,8 @@ pub(crate) use ptr_to_counter;
make_counters! {
yjit_insns_count,
+ // Method calls that fallback to dynamic dispatch
send_keywords,
- send_klass_megamorphic,
send_kw_splat,
send_args_splat_super,
send_iseq_zsuper,
@@ -245,11 +245,6 @@ make_counters! {
send_iseq_too_many_kwargs,
send_not_implemented_method,
send_getter_arity,
- send_se_cf_overflow,
- send_se_protected_check_failed,
- send_splatarray_length_not_equal,
- send_splatarray_last_ruby_2_keywords,
- send_splat_not_array,
send_args_splat_non_iseq,
send_args_splat_ivar,
send_args_splat_attrset,
@@ -268,10 +263,7 @@ make_counters! {
send_send_null_mid,
send_send_null_cme,
send_send_nested,
- send_send_chain,
send_send_chain_string,
- send_send_chain_not_string,
- send_send_chain_not_sym,
send_send_chain_not_string_or_sym,
send_send_getter,
send_send_builtin,
@@ -279,17 +271,27 @@ make_counters! {
send_iseq_has_rest_and_send,
send_iseq_has_rest_and_kw_supplied,
send_iseq_has_rest_opt_and_block,
- send_iseq_has_rest_and_splat_not_equal,
- send_is_a_class_mismatch,
- send_instance_of_class_mismatch,
- send_interrupted,
- send_not_fixnums,
- send_not_string,
- send_mid_mismatch,
-
send_bmethod_ractor,
send_bmethod_block_arg,
+ // Method calls that exit to the interpreter
+ guard_send_klass_megamorphic,
+ guard_send_se_cf_overflow,
+ guard_send_se_protected_check_failed,
+ guard_send_splatarray_length_not_equal,
+ guard_send_splatarray_last_ruby_2_keywords,
+ guard_send_splat_not_array,
+ guard_send_send_chain,
+ guard_send_send_chain_not_string,
+ guard_send_send_chain_not_sym,
+ guard_send_iseq_has_rest_and_splat_not_equal,
+ guard_send_is_a_class_mismatch,
+ guard_send_instance_of_class_mismatch,
+ guard_send_interrupted,
+ guard_send_not_fixnums,
+ guard_send_not_string,
+ guard_send_mid_mismatch,
+
traced_cfunc_return,
invokesuper_me_changed,