diff options
-rw-r--r-- | tool/ruby_vm/views/_mjit_compile_ivar.erb | 2 | ||||
-rw-r--r-- | vm.c | 2 | ||||
-rw-r--r-- | vm_core.h | 5 | ||||
-rw-r--r-- | vm_insnhelper.c | 20 |
4 files changed, 21 insertions, 8 deletions
diff --git a/tool/ruby_vm/views/_mjit_compile_ivar.erb b/tool/ruby_vm/views/_mjit_compile_ivar.erb index ab8e885b0b..cd5e81c831 100644 --- a/tool/ruby_vm/views/_mjit_compile_ivar.erb +++ b/tool/ruby_vm/views/_mjit_compile_ivar.erb @@ -15,7 +15,7 @@ % end % % # compiler: Consider cfp->self as T_OBJECT if ic->ic_serial is set - if (ic->ic_serial) { + if (ic->ic_serial >= RUBY_VM_CLASS_SERIAL_MIN_VALID_VALUE) { % # JIT: optimize away motion of sp and pc. This path does not call rb_warning() and so it's always leaf and not `handles_sp`. % # <%= render 'mjit_compile_pc_and_sp', locals: { insn: insn } -%> % @@ -340,7 +340,7 @@ rb_event_flag_t ruby_vm_event_flags; rb_event_flag_t ruby_vm_event_enabled_flags; rb_serial_t ruby_vm_global_method_state = 1; rb_serial_t ruby_vm_global_constant_state = 1; -rb_serial_t ruby_vm_class_serial = 1; +rb_serial_t ruby_vm_class_serial = RUBY_VM_CLASS_SERIAL_MIN_VALID_VALUE; static void thread_free(void *ptr); @@ -1846,4 +1846,9 @@ void rb_postponed_job_flush(rb_vm_t *vm); RUBY_SYMBOL_EXPORT_END +/* special values for ruby_vm_class_serial */ +#define RUBY_VM_CLASS_SERIAL_UNSET 0 /* Not cached yet. Fields in `is_entries` and `cc_entries` start from 0 due to ZALLOC_N. */ +#define RUBY_VM_CLASS_SERIAL_INVALID 1 /* Cache invalidated and never cached again. */ +#define RUBY_VM_CLASS_SERIAL_MIN_VALID_VALUE 2 /* Actual class serials are larger than this value. */ + #endif /* RUBY_VM_CORE_H */ diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 3f09991ba2..8c01a62d92 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -976,12 +976,20 @@ vm_getivar(VALUE obj, ID id, IC ic, struct rb_call_cache *cc, int is_attr) if (index < ROBJECT_NUMIV(obj)) { val = ROBJECT_IVPTR(obj)[index]; } - if (!is_attr) { - ic->ic_value.index = index; - ic->ic_serial = RCLASS_SERIAL(RBASIC(obj)->klass); - } - else { /* call_info */ - cc->aux.index = (int)index + 1; + if (is_attr) { /* call_info */ + cc->aux.index = (int)index + 1; + } + else { /* getinstancevariable */ + if (ic->ic_serial == RUBY_VM_CLASS_SERIAL_UNSET) { + /* set ic_serial only for the first time */ + ic->ic_value.index = index; + ic->ic_serial = RCLASS_SERIAL(RBASIC(obj)->klass); + } + else if (ic->ic_serial != RUBY_VM_CLASS_SERIAL_INVALID) { + /* never use cache for another class, to avoid race condition with MJIT worker + and to reduce the number of JIT cancellations by code generated for IC hit. */ + ic->ic_serial = RUBY_VM_CLASS_SERIAL_INVALID; + } } } } |