struct rb_callcache * gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, const struct rb_callinfo *ci) { /* snip */ // search global method cache unsigned int index = (unsigned int)(gccct_hash(klass, mid) % VM_GLOBAL_CC_CACHE_TABLE_SIZE); rb_vm_t *vm = rb_ec_vm_ptr(ec); const struct rb_callcache *cc = vm->global_cc_cache_table[index]; if (LIKELY(cc)) { if (LIKELY(vm_cc_class_check(cc, klass))) { const rb_callable_method_entry_t *cme = vm_cc_cme(cc); if (LIKELY(!METHOD_ENTRY_INVALIDATED(cme) && cme->called_id == mid)) { VM_ASSERT(vm_cc_check_cme(cc, rb_callable_method_entry(klass, mid))); return cc; } } } return gccct_method_search_slowpath(vm, klass, index, ci); } static inline const struct rb_callcache * gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, const struct rb_callinfo *ci) { /* snip */ // search global method cache unsigned int index = (unsigned int)(gccct_hash(klass, mid) % VM_GLOBAL_CC_CACHE_TABLE_SIZE); rb_vm_t *vm = rb_ec_vm_ptr(ec); const struct rb_callcache *cc = vm->global_cc_cache_table[index]; if (LIKELY(cc)) { if (LIKELY(vm_cc_class_check(cc, klass))) { const rb_callable_method_entry_t *cme = vm_cc_cme(cc); if (LIKELY(!METHOD_ENTRY_INVALIDATED(cme) && cme->called_id == mid)) { VM_ASSERT(vm_cc_check_cme(cc, rb_callable_method_entry(klass, mid))); return cc; } } } return gccct_method_search_slowpath(vm, klass, index, ci); } static inline const struct rb_callcache * gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, const struct rb_callinfo *ci) { /* snip */ // search global method cache unsigned int index = (unsigned int)(gccct_hash(klass, mid) % VM_GLOBAL_CC_CACHE_TABLE_SIZE); rb_vm_t *vm = rb_ec_vm_ptr(ec); const struct rb_callcache *cc = vm->global_cc_cache_table[index]; if (LIKELY(cc)) { if (LIKELY(vm_cc_class_check(cc, klass))) { const rb_callable_method_entry_t *cme = vm_cc_cme(cc); if (LIKELY(!METHOD_ENTRY_INVALIDATED(cme) && cme->called_id == mid)) { VM_ASSERT(vm_cc_check_cme(cc, rb_callable_method_entry(klass, mid))); return cc; } } } return gccct_method_search_slowpath(vm, klass, index, ci); } static inline const struct rb_callcache * gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, const struct rb_callinfo *ci) { /* snip */ // search global method cache unsigned int index = (unsigned int)(gccct_hash(klass, mid) % VM_GLOBAL_CC_CACHE_TABLE_SIZE); rb_vm_t *vm = rb_ec_vm_ptr(ec); const struct rb_callcache *cc = vm->global_cc_cache_table[index]; if (LIKELY(cc)) { if (LIKELY(vm_cc_class_check(cc, klass))) { const rb_callable_method_entry_t *cme = vm_cc_cme(cc); if (LIKELY(!METHOD_ENTRY_INVALIDATED(cme) && cme->called_id == mid)) { VM_ASSERT(vm_cc_check_cme(cc, rb_callable_method_entry(klass, mid))); return cc; } } } return gccct_method_search_slowpath(vm, klass, index, ci); } Lookup cache in global table Is the cache entry good? Slow path