YJIT: Distinguish exit and fallback reasons for send (#8159)

This commit is contained in:
Takashi Kokubun 2023-08-02 07:19:39 -07:00 committed by GitHub
parent 452debba22
commit 81c198b5cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
Notes: git 2023-08-02 14:20:00 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
3 changed files with 42 additions and 39 deletions

View File

@ -250,7 +250,8 @@ module RubyVM::YJIT
out.puts("***YJIT: Printing YJIT statistics on exit***") 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: 'invokeblock_', prompt: 'invokeblock exit reasons: ')
print_counters(stats, out: out, prefix: 'invokesuper_', prompt: 'invokesuper exit reasons: ') print_counters(stats, out: out, prefix: 'invokesuper_', prompt: 'invokesuper exit reasons: ')
print_counters(stats, out: out, prefix: 'leave_', prompt: 'leave exit reasons: ') print_counters(stats, out: out, prefix: 'leave_', prompt: 'leave exit reasons: ')

View File

@ -2574,7 +2574,7 @@ fn guard_two_fixnums(
asm: &mut Assembler, asm: &mut Assembler,
ocb: &mut OutlinedCb, ocb: &mut OutlinedCb,
) { ) {
let counter = Counter::send_not_fixnums; let counter = Counter::guard_send_not_fixnums;
// Get stack operands without popping them // Get stack operands without popping them
let arg1 = asm.stack_opnd(0); let arg1 = asm.stack_opnd(0);
@ -2779,7 +2779,7 @@ fn gen_equality_specialized(
a_opnd.into(), a_opnd.into(),
comptime_a, comptime_a,
SEND_MAX_DEPTH, SEND_MAX_DEPTH,
Counter::send_not_string, Counter::guard_send_not_string,
); );
let equal = asm.new_label("equal"); let equal = asm.new_label("equal");
@ -2806,7 +2806,7 @@ fn gen_equality_specialized(
b_opnd.into(), b_opnd.into(),
comptime_b, comptime_b,
SEND_MAX_DEPTH, 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.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(). // Codegen for rb_obj_not().
@ -4109,7 +4109,7 @@ fn jit_rb_kernel_is_a(
asm.comment("Kernel#is_a?"); asm.comment("Kernel#is_a?");
asm.cmp(asm.stack_opnd(0), sample_rhs.into()); 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); asm.stack_pop(2);
@ -4168,7 +4168,7 @@ fn jit_rb_kernel_instance_of(
asm.comment("Kernel#instance_of?"); asm.comment("Kernel#instance_of?");
asm.cmp(asm.stack_opnd(0), sample_rhs.into()); 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); asm.stack_pop(2);
@ -4544,7 +4544,7 @@ fn jit_rb_str_concat(
} }
// Guard that the concat argument is a string // 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, // 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(). // 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 // This is necessary because we have no guarantee that sym_opnd is a constant
asm.comment("guard known mid"); asm.comment("guard known mid");
asm.cmp(sym_opnd, mid_sym.into()); 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); jit_putobject(asm, result);
@ -5070,7 +5070,7 @@ fn gen_send_cfunc(
} }
// Check for interrupts // Check for interrupts
gen_check_ints(asm, Counter::send_interrupted); gen_check_ints(asm, Counter::guard_send_interrupted);
// Stack overflow check // Stack overflow check
// #define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin) // #define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin)
@ -5078,7 +5078,7 @@ fn gen_send_cfunc(
asm.comment("stack overflow check"); asm.comment("stack overflow check");
let stack_limit = asm.lea(asm.ctx.sp_opnd((SIZEOF_VALUE * 4 + 2 * RUBY_SIZEOF_CONTROL_FRAME) as isize)); 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.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 // Number of args which will be passed through to the callee
// This is adjusted by the kwargs being combined into a hash. // 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.comment("Side exit if length is less than required");
asm.cmp(array_len_opnd, num_args.into()); 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"); asm.comment("Push arguments from array");
@ -5380,7 +5380,7 @@ fn push_splat_args(required_args: u32, asm: &mut Assembler) {
asm, asm,
array_reg, array_reg,
array_opnd.into(), array_opnd.into(),
Counter::send_splat_not_array, Counter::guard_send_splat_not_array,
); );
asm.comment("Get array length for embedded or heap"); 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.comment("Side exit if length doesn't not equal remaining args");
asm.cmp(array_len_opnd, required_args.into()); 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"); 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( guard_object_is_not_ruby2_keyword_hash(
asm, asm,
last_array_value, last_array_value,
Counter::send_splatarray_last_ruby_2_keywords, Counter::guard_send_splatarray_last_ruby_2_keywords,
); );
asm.comment("Push arguments from array"); 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"); 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 })); 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.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) 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); 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)); let stack_limit = asm.lea(asm.ctx.sp_opnd(locals_offs as isize));
asm.cmp(CFP, stack_limit); 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 // push_splat_args does stack manipulation so we can no longer side exit
if let Some(array_length) = splat_array_length { if let Some(array_length) = splat_array_length {
@ -6626,7 +6626,7 @@ fn gen_send_general(
recv_opnd, recv_opnd,
comptime_recv, comptime_recv,
SEND_MAX_DEPTH, SEND_MAX_DEPTH,
Counter::send_klass_megamorphic, Counter::guard_send_klass_megamorphic,
); );
// Do method lookup // Do method lookup
@ -6834,12 +6834,12 @@ fn gen_send_general(
if compile_time_name.string_p() { if compile_time_name.string_p() {
( (
unsafe { rb_cString }, unsafe { rb_cString },
Counter::send_send_chain_not_string, Counter::guard_send_send_chain_not_string,
) )
} else { } else {
( (
unsafe { rb_cSymbol }, 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, asm,
ocb, ocb,
SEND_MAX_CHAIN_DEPTH, 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 // 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() { fn test_gen_check_ints() {
let (_jit, _ctx, mut asm, _cb, _ocb) = setup_codegen(); let (_jit, _ctx, mut asm, _cb, _ocb) = setup_codegen();
asm.set_side_exit_context(0 as _, 0); 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] #[test]

View File

@ -204,8 +204,8 @@ pub(crate) use ptr_to_counter;
make_counters! { make_counters! {
yjit_insns_count, yjit_insns_count,
// Method calls that fallback to dynamic dispatch
send_keywords, send_keywords,
send_klass_megamorphic,
send_kw_splat, send_kw_splat,
send_args_splat_super, send_args_splat_super,
send_iseq_zsuper, send_iseq_zsuper,
@ -245,11 +245,6 @@ make_counters! {
send_iseq_too_many_kwargs, send_iseq_too_many_kwargs,
send_not_implemented_method, send_not_implemented_method,
send_getter_arity, 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_non_iseq,
send_args_splat_ivar, send_args_splat_ivar,
send_args_splat_attrset, send_args_splat_attrset,
@ -268,10 +263,7 @@ make_counters! {
send_send_null_mid, send_send_null_mid,
send_send_null_cme, send_send_null_cme,
send_send_nested, send_send_nested,
send_send_chain,
send_send_chain_string, send_send_chain_string,
send_send_chain_not_string,
send_send_chain_not_sym,
send_send_chain_not_string_or_sym, send_send_chain_not_string_or_sym,
send_send_getter, send_send_getter,
send_send_builtin, send_send_builtin,
@ -279,17 +271,27 @@ make_counters! {
send_iseq_has_rest_and_send, send_iseq_has_rest_and_send,
send_iseq_has_rest_and_kw_supplied, send_iseq_has_rest_and_kw_supplied,
send_iseq_has_rest_opt_and_block, 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_ractor,
send_bmethod_block_arg, 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, traced_cfunc_return,
invokesuper_me_changed, invokesuper_me_changed,