YJIT: Use dynamic dispatch for megamorphic send (#8125)
This commit is contained in:
parent
e27eab2f85
commit
e5effa4bd0
Notes:
git
2023-07-27 17:09:38 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
4
yjit.rb
4
yjit.rb
@ -270,11 +270,14 @@ module RubyVM::YJIT
|
|||||||
out.puts "num_send: " + format_number(13, stats[:num_send])
|
out.puts "num_send: " + format_number(13, stats[:num_send])
|
||||||
out.puts "num_send_known_class: " + format_number_pct(13, stats[:num_send_known_class], stats[:num_send])
|
out.puts "num_send_known_class: " + format_number_pct(13, stats[:num_send_known_class], stats[:num_send])
|
||||||
out.puts "num_send_polymorphic: " + format_number_pct(13, stats[:num_send_polymorphic], stats[:num_send])
|
out.puts "num_send_polymorphic: " + format_number_pct(13, stats[:num_send_polymorphic], stats[:num_send])
|
||||||
|
out.puts "num_send_megamorphic: " + format_number_pct(13, stats[:num_send_megamorphic], stats[:num_send])
|
||||||
out.puts "num_send_dynamic: " + format_number_pct(13, stats[:num_send_dynamic], stats[:num_send])
|
out.puts "num_send_dynamic: " + format_number_pct(13, stats[:num_send_dynamic], stats[:num_send])
|
||||||
if stats[:num_send_x86_rel32] != 0 || stats[:num_send_x86_reg] != 0
|
if stats[:num_send_x86_rel32] != 0 || stats[:num_send_x86_reg] != 0
|
||||||
out.puts "num_send_x86_rel32: " + format_number(13, stats[:num_send_x86_rel32])
|
out.puts "num_send_x86_rel32: " + format_number(13, stats[:num_send_x86_rel32])
|
||||||
out.puts "num_send_x86_reg: " + format_number(13, stats[:num_send_x86_reg])
|
out.puts "num_send_x86_reg: " + format_number(13, stats[:num_send_x86_reg])
|
||||||
end
|
end
|
||||||
|
out.puts "num_getivar_megamorphic: " + format_number(13, stats[:num_getivar_megamorphic])
|
||||||
|
out.puts "num_setivar_megamorphic: " + format_number(13, stats[:num_setivar_megamorphic])
|
||||||
|
|
||||||
out.puts "iseq_stack_too_large: " + format_number(13, stats[:iseq_stack_too_large])
|
out.puts "iseq_stack_too_large: " + format_number(13, stats[:iseq_stack_too_large])
|
||||||
out.puts "iseq_too_long: " + format_number(13, stats[:iseq_too_long])
|
out.puts "iseq_too_long: " + format_number(13, stats[:iseq_too_long])
|
||||||
@ -302,7 +305,6 @@ module RubyVM::YJIT
|
|||||||
out.puts "freed_iseq_count: " + format_number(13, stats[:freed_iseq_count])
|
out.puts "freed_iseq_count: " + format_number(13, stats[:freed_iseq_count])
|
||||||
out.puts "invalidation_count: " + format_number(13, stats[:invalidation_count])
|
out.puts "invalidation_count: " + format_number(13, stats[:invalidation_count])
|
||||||
out.puts "constant_state_bumps: " + format_number(13, stats[:constant_state_bumps])
|
out.puts "constant_state_bumps: " + format_number(13, stats[:constant_state_bumps])
|
||||||
out.puts "get_ivar_max_depth: " + format_number(13, stats[:get_ivar_max_depth])
|
|
||||||
out.puts "inline_code_size: " + format_number(13, stats[:inline_code_size])
|
out.puts "inline_code_size: " + format_number(13, stats[:inline_code_size])
|
||||||
out.puts "outlined_code_size: " + format_number(13, stats[:outlined_code_size])
|
out.puts "outlined_code_size: " + format_number(13, stats[:outlined_code_size])
|
||||||
out.puts "code_region_size: " + format_number(13, stats[:code_region_size])
|
out.puts "code_region_size: " + format_number(13, stats[:code_region_size])
|
||||||
|
@ -1971,9 +1971,9 @@ fn gen_get_ivar(
|
|||||||
// Check if the comptime receiver is a T_OBJECT
|
// Check if the comptime receiver is a T_OBJECT
|
||||||
let receiver_t_object = unsafe { RB_TYPE_P(comptime_receiver, RUBY_T_OBJECT) };
|
let receiver_t_object = unsafe { RB_TYPE_P(comptime_receiver, RUBY_T_OBJECT) };
|
||||||
// Use a general C call at the last chain to avoid exits on megamorphic shapes
|
// Use a general C call at the last chain to avoid exits on megamorphic shapes
|
||||||
let last_chain = asm.ctx.get_chain_depth() as i32 == max_chain_depth - 1;
|
let megamorphic = asm.ctx.get_chain_depth() as i32 >= max_chain_depth;
|
||||||
if last_chain {
|
if megamorphic {
|
||||||
gen_counter_incr(asm, Counter::get_ivar_max_depth);
|
gen_counter_incr(asm, Counter::num_getivar_megamorphic);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the class uses the default allocator, instances should all be T_OBJECT
|
// If the class uses the default allocator, instances should all be T_OBJECT
|
||||||
@ -1981,7 +1981,7 @@ fn gen_get_ivar(
|
|||||||
// Eventually, we can encode whether an object is T_OBJECT or not
|
// Eventually, we can encode whether an object is T_OBJECT or not
|
||||||
// inside object shapes.
|
// inside object shapes.
|
||||||
// too-complex shapes can't use index access, so we use rb_ivar_get for them too.
|
// too-complex shapes can't use index access, so we use rb_ivar_get for them too.
|
||||||
if !receiver_t_object || uses_custom_allocator || comptime_receiver.shape_too_complex() || last_chain {
|
if !receiver_t_object || uses_custom_allocator || comptime_receiver.shape_too_complex() || megamorphic {
|
||||||
// General case. Call rb_ivar_get().
|
// General case. Call rb_ivar_get().
|
||||||
// VALUE rb_ivar_get(VALUE obj, ID id)
|
// VALUE rb_ivar_get(VALUE obj, ID id)
|
||||||
asm.comment("call rb_ivar_get()");
|
asm.comment("call rb_ivar_get()");
|
||||||
@ -2182,11 +2182,16 @@ fn gen_setinstancevariable(
|
|||||||
|
|
||||||
// Check if the comptime receiver is a T_OBJECT
|
// Check if the comptime receiver is a T_OBJECT
|
||||||
let receiver_t_object = unsafe { RB_TYPE_P(comptime_receiver, RUBY_T_OBJECT) };
|
let receiver_t_object = unsafe { RB_TYPE_P(comptime_receiver, RUBY_T_OBJECT) };
|
||||||
|
// Use a general C call at the last chain to avoid exits on megamorphic shapes
|
||||||
|
let megamorphic = asm.ctx.get_chain_depth() as i32 >= SET_IVAR_MAX_DEPTH;
|
||||||
|
if megamorphic {
|
||||||
|
gen_counter_incr(asm, Counter::num_setivar_megamorphic);
|
||||||
|
}
|
||||||
|
|
||||||
// If the receiver isn't a T_OBJECT, or uses a custom allocator,
|
// If the receiver isn't a T_OBJECT, or uses a custom allocator,
|
||||||
// then just write out the IV write as a function call.
|
// then just write out the IV write as a function call.
|
||||||
// too-complex shapes can't use index access, so we use rb_ivar_get for them too.
|
// too-complex shapes can't use index access, so we use rb_ivar_get for them too.
|
||||||
if !receiver_t_object || uses_custom_allocator || comptime_receiver.shape_too_complex() || (asm.ctx.get_chain_depth() as i32) >= SET_IVAR_MAX_DEPTH {
|
if !receiver_t_object || uses_custom_allocator || comptime_receiver.shape_too_complex() || megamorphic {
|
||||||
asm.comment("call rb_vm_setinstancevariable()");
|
asm.comment("call rb_vm_setinstancevariable()");
|
||||||
|
|
||||||
let ic = jit.get_arg(1).as_u64(); // type IVC
|
let ic = jit.get_arg(1).as_u64(); // type IVC
|
||||||
@ -6555,6 +6560,11 @@ fn gen_send_general(
|
|||||||
if asm.ctx.get_chain_depth() > 1 {
|
if asm.ctx.get_chain_depth() > 1 {
|
||||||
gen_counter_incr(asm, Counter::num_send_polymorphic);
|
gen_counter_incr(asm, Counter::num_send_polymorphic);
|
||||||
}
|
}
|
||||||
|
// If megamorphic, let the caller fallback to dynamic dispatch
|
||||||
|
if asm.ctx.get_chain_depth() as i32 >= SEND_MAX_DEPTH {
|
||||||
|
gen_counter_incr(asm, Counter::num_send_megamorphic);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
jit_guard_known_klass(
|
jit_guard_known_klass(
|
||||||
jit,
|
jit,
|
||||||
|
@ -396,9 +396,6 @@ make_counters! {
|
|||||||
|
|
||||||
constant_state_bumps,
|
constant_state_bumps,
|
||||||
|
|
||||||
// Not using "getivar_" to exclude this from exit reasons
|
|
||||||
get_ivar_max_depth,
|
|
||||||
|
|
||||||
// Currently, it's out of the ordinary (might be impossible) for YJIT to leave gaps in
|
// Currently, it's out of the ordinary (might be impossible) for YJIT to leave gaps in
|
||||||
// executable memory, so this should be 0.
|
// executable memory, so this should be 0.
|
||||||
exec_mem_non_bump_alloc,
|
exec_mem_non_bump_alloc,
|
||||||
@ -407,11 +404,15 @@ make_counters! {
|
|||||||
|
|
||||||
num_send,
|
num_send,
|
||||||
num_send_known_class,
|
num_send_known_class,
|
||||||
|
num_send_megamorphic,
|
||||||
num_send_polymorphic,
|
num_send_polymorphic,
|
||||||
num_send_x86_rel32,
|
num_send_x86_rel32,
|
||||||
num_send_x86_reg,
|
num_send_x86_reg,
|
||||||
num_send_dynamic,
|
num_send_dynamic,
|
||||||
|
|
||||||
|
num_getivar_megamorphic,
|
||||||
|
num_setivar_megamorphic,
|
||||||
|
|
||||||
iseq_stack_too_large,
|
iseq_stack_too_large,
|
||||||
iseq_too_long,
|
iseq_too_long,
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user