1 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.46 $ */
2 /* Copyright (c) 2006, Sun Microsystems, Inc.
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
6 following conditions are met:
8 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
10 disclaimer in the documentation and/or other materials provided with the distribution.
11 * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived
12 from this software without specific prior written permission.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
15 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
16 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
18 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
19 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
24 # include "incls/_precompiled.incl"
26 # ifdef DELTA_COMPILER
27 # include "incls/_compiledIC.cpp.incl"
30 extern "C" void UncommonTrap() {
32 DeltaProcess::active()->trace_stack();
33 error("Uncommon trap has been executed");
34 evaluator::read_eval_loop();
38 char* CompiledIC::normalLookupRoutine() {
39 return StubRoutines::ic_normal_lookup_entry();
43 char* CompiledIC::superLookupRoutine() {
44 return StubRoutines::ic_super_lookup_entry();
48 extern "C" char* icNormalLookup(oop recv
, CompiledIC
* ic
) {
49 // As soon as the lookup routine handles 'message not understood' correctly,
50 // allocation may take place. Then we have to fix the lookup stub as well.
51 // (receiver cannot be saved/restored within the C frame).
53 return ic
->normalLookup(recv
);
57 bool CompiledIC::is_empty() const {
58 char* d
= destination();
59 return d
== normalLookupRoutine() || d
== superLookupRoutine();
63 int CompiledIC::ntargets() const {
64 if (is_empty()) return 0;
66 return p
!= NULL
? p
->number_of_targets() : 1;
70 void CompiledIC::set_call_destination(char* entry_point
) {
71 // if the IC has a PIC we deallocate the PIC before setting the entry_point
73 assert(p
== NULL
|| p
->entry() != entry_point
, "replacing with same address -- shouldn't dealloc");
74 if (p
!= NULL
) delete p
;
75 NativeCall::set_destination(entry_point
);
79 extern "C" bool have_nlr_through_C
;
81 oop
nmethod_substitute() {
82 return Universe::nilObj();
86 char* CompiledIC::normalLookup(oop recv
) {
90 // The assertion below is turned into an if so we can see
91 // possible problems in the fast version as well - gri 6/21/96
93 // Last problem reported by Steffen (gri 7/24/96): This has been
94 // called via a nmethod called from within a megamorphic self send
95 // in the interpreter. I've added Interpreter::_last_native_called
96 // for better debugging.
98 // assert(!Interpreter::contains(begin_addr()), "should be handled in the interpreter");
99 if (Interpreter::contains(begin_addr())) {
100 std
->print_cr("nmethod called from interpreter reports ic miss:");
101 std
->print_cr("interpreter call at: 0x%x", begin_addr());
102 std
->print_cr("nmethod entry point: 0x%x", Interpreter::_last_native_called
);
103 InterpretedIC
* ic
= as_InterpretedIC(next_instruction_address());
104 fatal("please notify VM people");
108 std
->print("CompiledIC lookup (");
109 recv
->klass()->print_value();
111 selector()->print_value();
115 klassOop klass
= recv
->klass();
116 symbolOop sel
= selector();
117 LookupResult result
= lookupCache::ic_normal_lookup(klass
, sel
);
119 if (result
.is_empty()) {
120 // does not understand
122 // The following code is just a copy from the corresponding section
123 // for interpreted code - especially the arguments for the message
124 // object are not set up yet (0 arguments assumed). This code is
125 // only here to prevent the system from crashing completely - in
126 // general one should be able to recover using abort in the evaluator.
128 // FIX THIS (gri 6/10/96)
129 BlockScavenge bs
; // make sure that no scavenge happens
130 klassOop msgKlass
= klassOop(Universe::find_global("Message"));
131 oop obj
= msgKlass
->klass_part()->allocateObject();
132 assert(obj
->is_mem(), "just checkin'...");
133 memOop msg
= memOop(obj
);
134 objArrayOop args
= oopFactory::new_objArray(0);
135 // for now: assume instance variables are there...
136 // later: should check this or use a VM interface:
137 // msg->set_receiver(recv);
138 // msg->set_selector(ic->selector());
139 // msg->set_arguments(args);
140 msg
->raw_at_put(2, recv
);
141 msg
->raw_at_put(3, selector());
142 msg
->raw_at_put(4, args
);
143 symbolOop sel
= oopFactory::new_symbol("doesNotUnderstand:");
144 if (interpreter_normal_lookup(recv
->klass(), sel
).is_empty()) {
145 // doesNotUnderstand: not found ==> process error
147 std
->print("LOOKUP ERROR\n");
148 sel
->print_value(); std
->print(" not found\n");
150 if (DeltaProcess::active()->is_scheduler()) {
151 DeltaProcess::active()->trace_stack();
152 fatal("lookup error in scheduler");
154 DeltaProcess::active()->suspend(::lookup_error
);
156 ShouldNotReachHere();
158 // return marked result of doesNotUnderstand: message
159 oop result
= Delta::call(recv
, sel
, msg
);
161 if (!have_nlr_through_C
) {
164 // return a substitute nmethod so that stub routine doesn't crash
165 return (char*)nmethod_substitute
;
167 /* Old code - keep around till completely fixed
169 LookupKey key(klass, sel);
171 std->print("Compiled lookup failed for: ");
175 DeltaProcess::active()->trace_stack();
176 warning("Lookup error: DoesNotUnderstand semantics not implemented for compiled code");
177 evaluator::read_eval_loop();
182 if (isOptimized() && result
.is_method()) {
183 // If this call site is optimized only nmethods should be called.
184 assert(!isMegamorphic(), "megamorphic ICs shouldn't be optimized");
185 LookupKey
key(klass
, sel
);
186 VM_OptimizeMethod
op(&key
, result
.method());
187 VMProcess::execute(&op
);
188 result
= lookupCache::ic_normal_lookup(klass
, sel
);
189 assert(result
.is_entry(), "result must contain a jump table entry");
192 bool empty
= is_empty();
193 if (empty
) setDirty();
194 if (!empty
|| result
.is_method()) {
195 PIC
* pic
= PIC::allocate(this, klass
, result
);
197 // PIC too large & MICs (megamorphic PICs) turned off
198 // => start with empty IC again
199 assert(!UseMICs
, "should return a MIC");
201 if (result
.is_entry()) {
202 entry_point
= isReceiverStatic()
203 ? result
.entry()->method()->verifiedEntryPoint()
204 : result
.entry()->destination();
206 pic
= PIC::allocate(this, klass
, result
);
207 assert(pic
!= NULL
, "pic must be present");
208 entry_point
= pic
->entry();
211 entry_point
= pic
->entry();
212 if (pic
->is_megamorphic()) {
213 setMegamorphic(); // even when UseInlineCaching is turned off? (gri 5/24/96) - check this
217 assert(empty
&& result
.is_entry(), "just checking");
219 // result is a jump table entry for an nmethod
220 if (TraceLookup2
) lprintf("nmethod found, f = 0x%x\n", result
.get_nmethod());
221 // fetch the destination of the jump table entry to avoid the indirection
223 // is the receiver is static we will use the verified entry point
224 entry_point
= isReceiverStatic()
225 ? result
.entry()->method()->verifiedEntryPoint()
226 : result
.entry()->destination();
228 assert(isDirty(), "must be dirty now"); // important invariant for type feedback: non-empty IC must be dirty
229 if (UseInlineCaching
) set_call_destination(entry_point
);
230 if (TraceLookup2
) print();
231 LOG_EVENT3("CompiledICLookup (%#x, %#x) --> %#x", klass
, sel
, entry_point
);
236 extern "C" char* icSuperLookup(oop recv
, CompiledIC
* ic
) {
237 // As soon as the lookup routine handles 'message not understood' correctly,
238 // allocation may take place. Then we have to fix the lookup stub as well.
239 // (receiver cannot be saved/restored within the C frame).
240 VerifyNoScavenge vna
;
241 return ic
->superLookup(recv
);
245 extern "C" char* zombie_nmethod(char* return_addr
) {
246 // Called from zombie nmethods. Determines if called from interpreted
247 // or compiled code, does cleanup of the corresponding inline caches
248 // and restarts the send.
250 // Note: If the nmethod is called from within the interpreter, the
251 // send restart entry point is computed via a 2nd ic_info word
252 // that follows the ordinary ic_info associated with the call.
253 // (the same method as for NLRs used, the target is the send
254 // restart entry point).
255 VerifyNoScavenge vna
;
256 if (Interpreter::contains(return_addr
)) {
257 // nmethod called from interpreted code
258 frame f
= DeltaProcess::active()->last_frame();
259 InterpretedIC
* ic
= f
.current_interpretedIC();
260 LOG_EVENT1("zombie nmethod called => interpreted IC 0x%x cleared", ic
);
262 // reset instruction pointer => next instruction beeing executed is the same send
263 f
.set_hp(ic
->send_code_addr());
264 // restart send entry point for interpreted sends
265 return Interpreter::redo_send_entry();
267 // nmethod called from compiled code
268 CompiledIC
* ic
= CompiledIC_from_return_addr(return_addr
);
269 LOG_EVENT1("zombie nmethod called => compiled IC 0x%x cleaned up", ic
);
271 // restart send entry point is call address
272 return ic
->begin_addr();
277 klassOop
CompiledIC::targetKlass() const {
278 nmethod
* nm
= target();
280 return nm
->key
.klass();
282 Unimplemented(); return NULL
;
287 klassOop
CompiledIC::sending_method_holder() {
288 char* addr
= begin_addr();
289 nmethod
* nm
= findNMethod(addr
);
290 PcDesc
* pcdesc
= nm
->containingPcDesc(addr
);
291 ScopeDesc
* scope
= pcdesc
->containingDesc(nm
);
292 return scope
->selfKlass()->klass_part()->lookup_method_holder_for(scope
->method());
296 char* CompiledIC::superLookup(oop recv
) {
299 assert(!Interpreter::contains(begin_addr()), "should be handled in the interpreter");
301 klassOop recv_klass
= recv
->klass();
302 klassOop mhld_klass
= sending_method_holder();
303 symbolOop sel
= selector();
306 std
->print("CompiledIC super lookup (");
307 recv_klass
->print_value();
309 mhld_klass
->print_value();
311 selector()->print_value();
316 // The inline cache for super sends looks like the inline cache
319 LookupResult result
= lookupCache::ic_super_lookup(recv_klass
, mhld_klass
->klass_part()->superKlass(), sel
);
320 assert(!result
.is_empty(), "lookup cache error");
321 if (result
.is_method()) {
323 if (TraceLookup2
) lprintf("methodOop found, m = 0x%x\n", result
.method());
324 // result = (char*)&interpreter_call;
325 // if (UseInlineCaching) set_call_destination(result);
326 warning("CompiledIC::superLookup didn't find a nmethod - check this");
329 // result is a jump table entry for an nmethod
330 if (TraceLookup2
) lprintf("nmethod %#x found\n", result
.get_nmethod());
331 // fetch the destination of the jump table entry to avoid the indirection
332 entry_point
= result
.entry()->destination();
334 if (UseInlineCaching
) set_call_destination(entry_point
);
335 if (TraceLookup2
) print();
336 LOG_EVENT3("SuperLookup (%#x, %#x) --> %#x", recv_klass
, sel
, entry_point
);
341 bool CompiledIC::is_monomorphic() const {
342 if (target() != NULL
) return true;
344 return p
!= NULL
&& p
->is_monomorphic();
348 bool CompiledIC::is_polymorphic() const {
350 return p
!= NULL
&& p
->is_polymorphic();
354 bool CompiledIC::is_megamorphic() const {
356 return p
!= NULL
&& p
->is_megamorphic();
360 void CompiledIC::replace(nmethod
* nm
) {
361 assert(selector() == nm
->key
.selector(), "mismatched selector");
362 LOG_EVENT3("compiled IC at 0x%x: new nmethod 0x%x for klass 0x%x replaces old entry", this, nm
, nm
->key
.klass());
365 if (is_monomorphic()) {
367 assert(pic()->klasses()->at(0) == nm
->key
.klass(), "mismatched klass");
369 // verify the key in the old nmethod matches the new
370 assert(findNMethod(destination())->key
.equal(&nm
->key
), "keys must match");
372 // set_call_destination deallocates the pic if necessary.
373 set_call_destination(nm
->entryPoint());
379 PIC
* new_pic
= p
->replace(nm
);
381 set_call_destination(new_pic
->entry());
386 ShouldNotReachHere();
390 void CompiledIC::clear() {
391 // Fix this when compiler is more flexible
392 assert(!isSuperSend() || UseNewBackend
, "We cannot yet have super sends in nmethods");
395 set_call_destination(isSuperSend() ? superLookupRoutine() : normalLookupRoutine());
397 // Q: Are there any flags to be reset and if so, which ones?
398 // A: No, they are "invariant" properties of the IC. Even the dirty bit should not be
399 // reset, otherwise the compiler may think it was never executed. -Urs 7/96
403 void CompiledIC::cleanup() {
404 // Convert all entries using the following rules:
406 // nmethod -> nmethod (nothing changed)
407 // or nmethod' (new nmethod has been compiled)
408 // or methodOop (old nmethod is invalid)
410 // methodOop -> methodOop (nothing changed)
411 // or nmethod (new nmethod has been compiled)
414 if (is_empty()) return;
417 if (is_monomorphic()) {
419 // Must be interpreter send
420 PIC_Iterator
it(pic());
421 assert(it
.is_interpreted(), "must be interpreted send in monomorphic case");
422 // Since it is impossible to retrieve the sending method for a methodOop
423 // we leave the IC unchanged if we're in a super send.
424 if (isSuperSend()) return;
425 LookupKey
key(it
.get_klass(), selector());
426 LookupResult result
= lookupCache::lookup(&key
);
427 // Nothing to do if lookup result is the same
428 if (result
.matches(it
.interpreted_method())) return;
429 // Otherwise update IC depending on lookup result
430 if (result
.is_empty()) {
432 } else if (result
.is_method()) {
433 it
.set_methodOop(result
.method());
435 assert(result
.is_entry(), "lookup result should be a jump table entry");
436 set_call_destination(result
.get_nmethod()->entryPoint());
440 nmethod
* old_nm
= findNMethod(destination());
441 LookupResult result
= lookupCache::lookup(&old_nm
->key
);
442 // Nothing to do if lookup result is the same
443 if (result
.matches(old_nm
)) return;
444 // Otherwise update IC depending on lookup result
445 if (result
.is_empty()) {
447 } else if (result
.is_method()) {
448 // don't set to interpreted method -- may be "compiled only" send
451 assert(result
.is_entry(), "lookup result should be a jump table entry");
452 set_call_destination(result
.get_nmethod()->entryPoint());
454 /* Old code for compiled target - remove if new version works (gri 7/17/96)
456 nmethod* nm = findNMethod(destination());
457 LookupResult result = lookupCache::lookup(&nm->key);
458 assert(nm->isZombie() || result.is_entry(), "lookup cache is wrong");
459 // Nothing to do if lookup result is the same
460 if (result.matches(nm)) return;
461 assert(nm->isZombie(), "nmethod should be zombie");
462 nmethod* newNM = result.get_nmethod();
464 set_call_destination(newNM->entryPoint());
466 clear(); // don't set to interpreted method -- may be "compiled only" send
477 PIC
* result
= p
->cleanup(&nm
);
481 set_call_destination(result
->entry());
485 set_call_destination(nm
->entryPoint());
496 ShouldNotReachHere();
500 void CompiledIC::print() {
501 ResourceMark rm
; // so we can print from debugger
502 lprintf("\t((CompiledIC*)%#x) ", this);
506 lprintf("(filled: %d targets) ", ntargets());
508 if (isReceiverStatic()) lprintf("static ");
509 if (isDirty()) lprintf("dirty ");
510 if (isOptimized()) lprintf("optimized ");
511 if (isUninlinable()) lprintf("uninlinable ");
512 if (isSuperSend()) lprintf("super ");
513 if (isMegamorphic()) lprintf("megamorphic ");
516 lprintf("\t- selector : ");
517 selector()->print_symbol_on();
520 CompiledIC_Iterator
it(this);
521 while (!it
.at_end()) {
522 lprintf("\t- klass : ");
523 it
.klass()->print_value();
524 if (it
.is_compiled()) {
525 lprintf(";\tnmethod %#x\n", it
.compiled_method());
527 lprintf(";\tmethod %#x\n", it
.interpreted_method());
532 lprintf("\t- call address: ");
533 char* dest
= destination();
534 if (dest
== normalLookupRoutine()) {
535 lprintf("normalLookupRoutine\n");
536 } else if (dest
== superLookupRoutine()) {
537 lprintf("superLookupRoutine\n");
540 lprintf("0x%x\n", destination());
543 lprintf("\t- NLR testcode: 0x%x\n", NLR_testcode());
547 InterpretedIC
* CompiledIC::inlineCache() const {
548 // return interpreter inline cache in corresponding source method
549 char* addr
= begin_addr();
550 nmethod
* nm
= findNMethod(addr
);
551 PcDesc
* pcdesc
= nm
->containingPcDesc(addr
);
552 ScopeDesc
* scope
= pcdesc
->containingDesc(nm
);
553 CodeIterator iter
= CodeIterator(scope
->method(), pcdesc
->byteCode
);
558 symbolOop
CompiledIC::selector() const {
559 return inlineCache()->selector();
563 nmethod
* CompiledIC::target() const {
564 char* dest
= destination();
565 if (Universe::code
->contains(dest
)) {
566 // linked to an nmethod
567 nmethod
* m
= nmethod_from_insts(dest
);
568 assert(m
== findNMethod(dest
), "wrong nmethod start");
576 klassOop
CompiledIC::get_klass(int i
) const {
580 for (int j
= 0; j
< i
; j
++) it
.advance();
581 return it
.get_klass();
583 assert(i
== 0, "have max. 1 target method");
584 return target()->key
.klass();
589 PIC
* CompiledIC::pic() const {
590 char* dest
= destination();
591 return PIC::find(dest
);
595 LookupKey
* CompiledIC::key(int i
, bool is_normal_send
) const {
596 if (is_normal_send
) {
597 return LookupKey::allocate(get_klass(i
), selector());
599 CompiledIC_Iterator
it((CompiledIC
*)this);
601 return LookupKey::allocate(it
.klass(), it
.interpreted_method());
606 bool CompiledIC::wasNeverExecuted() const {
607 return is_empty() && !isDirty();
610 primitive_desc
* PrimitiveIC::primitive() {
611 return primitives::lookup((fntype
) destination());
615 char* PrimitiveIC::end_addr() {
616 primitive_desc
* pd
= primitive();
617 int offset
= pd
->can_perform_NLR() ? IC_Info::instruction_size
: 0;
618 return next_instruction_address() + offset
;
622 void PrimitiveIC::print() {
623 lprintf("\tPrimitive inline cache\n");
624 primitive_desc
* pd
= primitive();
625 lprintf("\t- name : %s\n", pd
->name());
626 if (pd
->can_perform_NLR()) {
627 lprintf("\t- NLR testcode: 0x%x\n", NLR_testcode());
633 // Dummy for avoiding link error for system without the DELTA_COMPILER
634 extern "C" void icLookup(int a
, int b
) {}
635 extern "C" void icNormalLookup(int a
, int b
) {}
636 extern "C" void icSuperLookup(int a
, int b
) {}