YJIT: Distinguish exit and fallback reasons for send (#8159)
This commit is contained in:
parent
452debba22
commit
81c198b5cf
Notes:
git
2023-08-02 14:20:00 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
3
yjit.rb
3
yjit.rb
@ -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: ')
|
||||||
|
@ -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]
|
||||||
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user