oop* InterpretedIC::inline_cache_miss() { NoGCVerifier noGC; // get ic info frame f = DeltaProcess::active()->last_frame(); InterpretedIC* ic = f.current_interpretedIC(); Bytecodes::Code send_code = ic->send_code(); oop receiver = ic->argument_spec() == Bytecodes::args_only // Are we at a self or super send? ? f.receiver() // yes: take receiver of frame : f.expr(ic->nof_arguments()); // no: take receiver pushed before the arguments // do the lookup klassOop klass = receiver->klass(); LookupResult result = Bytecodes::is_super_send(send_code) ? interpreter_super_lookup(ic->selector()) : interpreter_normal_lookup(klass, ic->selector()); // tracing if (TraceInlineCacheMiss) { std->print("IC miss, "); trace_inline_cache_miss(ic, klass, result); } // handle the lookup result if (!result.is_empty()) { update_inline_cache(ic, &f, ic->send_code(), klass, result); return NULL; } else { return cacheMissResult(does_not_understand(receiver, ic, &f), ic->nof_arguments() + (ic->argument_spec() == Bytecodes::args_only ? 0 : 1))->objs(1); } }
void InterpretedIC::inline_cache_miss() { NoGCVerifier noGC; // get ic info frame f = DeltaProcess::active()->last_frame(); InterpretedIC* ic = f.current_interpretedIC(); Bytecodes::Code send_code = ic->send_code(); oop receiver = ic->argument_spec() == Bytecodes::args_only // Are we at a self or super send? ? f.receiver() // yes: take receiver of frame : f.expr(ic->nof_arguments()); // no: take receiver pushed before the arguments // do the lookup klassOop klass = receiver->klass(); LookupResult result = Bytecodes::is_super_send(send_code) ? interpreter_super_lookup(ic->selector()) : interpreter_normal_lookup(klass, ic->selector()); // tracing if (TraceMessageSend) std->print_cr("inline cache miss"); if (TraceLookup) trace_inline_cache_miss(ic, klass, result); // handle the lookup result if (!result.is_empty()) update_inline_cache(ic, &f, send_code, klass, result); else { does_not_understand(receiver, ic, &f); // If the program continues we'll redo the inline_cache_miss if (!have_nlr_through_C) inline_cache_miss(); } }
LookupResult lookup(klassOop klass, symbolOop selector) { if (!match(klass, selector)) { _result = interpreter_normal_lookup(klass, selector); if (!_result.is_empty()) { _key.initialize(klass, selector); } } return _result; }
void InterpretedIC::replace(LookupResult result, klassOop receiver_klass) { // IC entries before modification - used for loging only Bytecodes::Code code_before = send_code(); oop word1_before = first_word(); oop word2_before = second_word(); int transition = 0; // modify IC guarantee(word2_before == receiver_klass, "klass should be the same"); if (result.is_empty()) { clear(); transition = 1; } else if (result.is_method()) { if (send_type() == Bytecodes::megamorphic_send) { set(send_code(), result.method(), receiver_klass); transition = 2; } else { // Please Fix this Robert // implement set_monomorphic(klass, method) clear(); transition = 3; } } else { if (send_type() == Bytecodes::megamorphic_send) { set(send_code(), oop(result.entry()), receiver_klass); transition = 4; } else { assert(result.is_entry(), "must be jump table entry"); // a jump table entry of a nmethod is found so let's update the current send set(Bytecodes::compiled_send_code_for(send_code()), oop(result.entry()), receiver_klass); transition = 5; } } // IC entries after modification - used for loging only Bytecodes::Code code_after = send_code(); oop word1_after = first_word(); oop word2_after = second_word(); // log modification LOG_EVENT3("InterpretedIC::replace: IC at 0x%x: entry for klass 0x%x replaced (transition %d)", this, receiver_klass, transition); LOG_EVENT3(" from (%s, 0x%x, 0x%x)", Bytecodes::name(code_before), word1_before, word2_before); LOG_EVENT3(" to (%s, 0x%x, 0x%x)", Bytecodes::name(code_after ), word1_after , word2_after ); }