Object* PolyInlineCache::check_cache(STATE, CallSite* call_site, Arguments& args) { Class* const recv_class = args.recv()->direct_class(state); PolyInlineCache* cache = static_cast<PolyInlineCache*>(call_site); InlineCacheEntry* entry = cache->get_entry(recv_class); if(likely(entry)) { Executable* meth = entry->method(); Module* mod = entry->stored_module(); entry->hit(); state->vm()->metrics().machine.methods_invoked++; return meth->execute(state, meth, mod, args); } return cache->fallback(state, args); }
InlineCacheEntry* InlineCacheEntry::create(STATE, ClassData data, Class* klass, Dispatch& dis, int hits) { InlineCacheEntry* cache = state->memory()->new_object_pinned<InlineCacheEntry>(state, G(inline_cache_entry)); cache->receiver_data(data); cache->receiver_class(state, klass); cache->stored_module(state, dis.module); cache->method(state, dis.method); cache->method_missing(dis.method_missing); cache->hits(hits); return cache; }
bool CallSite::update_and_validate(STATE, CallFrame* call_frame, Object* recv, Symbol* vis, int serial) { Class* const recv_class = recv->lookup_begin(state); if(MonoInlineCache* mono = try_as<MonoInlineCache>(this)) { if(recv_class->data_raw() == mono->receiver_data_raw()) { return mono->method()->serial()->to_native() == serial; } } if(PolyInlineCache* cache = try_as<PolyInlineCache>(this)) { InlineCacheEntry* ice = cache->get_entry(recv_class); if(likely(ice)) return ice->method()->serial()->to_native() == serial; } LookupData lookup(call_frame->self(), recv_class, G(sym_public)); Dispatch dis(name_); if(dis.resolve(state, name_, lookup)) { update(state, recv_class, dis); return dis.method->serial()->to_native() == serial; } return false; }