From b9007b6c548f91e88fd3f2ffa23de740431fa969 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Wed, 8 Jan 2020 16:14:01 +0900 Subject: Introduce disposable call-cache. This patch contains several ideas: (1) Disposable inline method cache (IMC) for race-free inline method cache * Making call-cache (CC) as a RVALUE (GC target object) and allocate new CC on cache miss. * This technique allows race-free access from parallel processing elements like RCU. (2) Introduce per-Class method cache (pCMC) * Instead of fixed-size global method cache (GMC), pCMC allows flexible cache size. * Caching CCs reduces CC allocation and allow sharing CC's fast-path between same call-info (CI) call-sites. (3) Invalidate an inline method cache by invalidating corresponding method entries (MEs) * Instead of using class serials, we set "invalidated" flag for method entry itself to represent cache invalidation. * Compare with using class serials, the impact of method modification (add/overwrite/delete) is small. * Updating class serials invalidate all method caches of the class and sub-classes. * Proposed approach only invalidate the method cache of only one ME. See [Feature #16614] for more details. --- vm.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'vm.c') diff --git a/vm.c b/vm.c index 7482db1b54..50e317408b 100644 --- a/vm.c +++ b/vm.c @@ -386,6 +386,8 @@ 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; +const struct rb_callcache *vm_empty_cc; + static void thread_free(void *ptr); void @@ -2806,8 +2808,9 @@ static VALUE m_core_undef_method(VALUE self, VALUE cbase, VALUE sym) { REWIND_CFP({ - rb_undef(cbase, SYM2ID(sym)); - rb_clear_method_cache_by_class(self); + ID mid = SYM2ID(sym); + rb_undef(cbase, mid); + rb_clear_method_cache(self, mid); }); return Qnil; } @@ -2962,6 +2965,13 @@ f_lambda(VALUE _) return rb_block_lambda(); } +static VALUE +vm_mtbl(VALUE self, VALUE obj, VALUE sym) +{ + vm_mtbl_dump(CLASS_OF(obj), SYM2ID(sym)); + return Qnil; +} + void Init_VM(void) { @@ -3249,9 +3259,11 @@ Init_VM(void) #if VMDEBUG rb_define_singleton_method(rb_cRubyVM, "SDR", sdr, 0); rb_define_singleton_method(rb_cRubyVM, "NSDR", nsdr, 0); + rb_define_singleton_method(rb_cRubyVM, "mtbl", vm_mtbl, 2); #else (void)sdr; (void)nsdr; + (void)vm_mtbl; #endif /* VM bootstrap: phase 2 */ @@ -3348,6 +3360,10 @@ Init_vm_objects(void) vm->frozen_strings = st_init_table_with_size(&rb_fstring_hash_type, 10000); rb_objspace_gc_enable(vm->objspace); + + vm_empty_cc = vm_cc_new(0, NULL, vm_call_general); + FL_SET_RAW(vm_empty_cc, VM_CALLCACHE_UNMARKABLE); + rb_gc_register_mark_object((VALUE)vm_empty_cc); } /* top self */ @@ -3716,6 +3732,12 @@ vm_collect_usage_register(int reg, int isset) } #endif +MJIT_FUNC_EXPORTED const struct rb_callcache * +rb_vm_empty_cc(void) +{ + return vm_empty_cc; +} + #endif /* #ifndef MJIT_HEADER */ #include "vm_call_iseq_optimized.inc" /* required from vm_insnhelper.c */ -- cgit v1.2.3