made a copy
[strongtalk-kjk.git] / vm / code / compiledIC.cpp
blob1dcadc91d8a8e99dc166933a2c8654a1402aa81d
1 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.46 $ */
2 /* Copyright (c) 2006, Sun Microsystems, Inc.
3 All rights reserved.
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() {
31 ResourceMark rm;
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).
52 VerifyNoScavenge vna;
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;
65 PIC* p = pic();
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
72 PIC* p = pic();
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) {
87 ResourceMark rm;
88 char* entry_point;
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");
107 if (TraceLookup) {
108 std->print("CompiledIC lookup (");
109 recv->klass()->print_value();
110 std->print(", ");
111 selector()->print_value();
112 std->print(")");
113 std->cr();
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
146 { ResourceMark rm;
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");
153 } else {
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) {
162 Unimplemented();
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: ");
172 key.print_on(std);
173 std->cr();
175 DeltaProcess::active()->trace_stack();
176 warning("Lookup error: DoesNotUnderstand semantics not implemented for compiled code");
177 evaluator::read_eval_loop();
178 Unimplemented();
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);
196 if (pic == NULL) {
197 // PIC too large & MICs (megamorphic PICs) turned off
198 // => start with empty IC again
199 assert(!UseMICs, "should return a MIC");
200 clear();
201 if (result.is_entry()) {
202 entry_point = isReceiverStatic()
203 ? result.entry()->method()->verifiedEntryPoint()
204 : result.entry()->destination();
205 } else {
206 pic = PIC::allocate(this, klass, result);
207 assert(pic != NULL, "pic must be present");
208 entry_point = pic->entry();
210 } else {
211 entry_point = pic->entry();
212 if (pic->is_megamorphic()) {
213 setMegamorphic(); // even when UseInlineCaching is turned off? (gri 5/24/96) - check this
216 } else {
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);
232 return 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);
261 ic->cleanup();
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();
266 } else {
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);
270 ic->cleanup();
271 // restart send entry point is call address
272 return ic->begin_addr();
277 klassOop CompiledIC::targetKlass() const {
278 nmethod* nm = target();
279 if (nm) {
280 return nm->key.klass();
281 } else {
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) {
297 ResourceMark rm;
298 char* entry_point;
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();
305 if (TraceLookup) {
306 std->print("CompiledIC super lookup (");
307 recv_klass->print_value();
308 std->print(", ");
309 mhld_klass->print_value();
310 std->print(", ");
311 selector()->print_value();
312 std->print(")");
313 std->cr();
316 // The inline cache for super sends looks like the inline cache
317 // for normal sends.
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()) {
322 // a methodOop
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");
327 Unimplemented();
328 } else {
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);
337 return entry_point;
341 bool CompiledIC::is_monomorphic() const {
342 if (target() != NULL) return true;
343 PIC* p = pic();
344 return p != NULL && p->is_monomorphic();
348 bool CompiledIC::is_polymorphic() const {
349 PIC* p = pic();
350 return p != NULL && p->is_polymorphic();
354 bool CompiledIC::is_megamorphic() const {
355 PIC* p = pic();
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());
364 // MONO
365 if (is_monomorphic()) {
366 if (pic()) {
367 assert(pic()->klasses()->at(0) == nm->key.klass(), "mismatched klass");
368 } else {
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());
374 return;
376 // POLY or MEGA
377 PIC* p = pic();
378 if (p != NULL) {
379 PIC* new_pic = p->replace(nm);
380 if (new_pic != p) {
381 set_call_destination(new_pic->entry());
383 return;
385 // EMPTY
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");
394 // Clear destination
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)
413 // EMPTY
414 if (is_empty()) return;
416 // MONOMORPHIC
417 if (is_monomorphic()) {
418 if (pic()) {
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()) {
431 clear();
432 } else if (result.is_method()) {
433 it.set_methodOop(result.method());
434 } else {
435 assert(result.is_entry(), "lookup result should be a jump table entry");
436 set_call_destination(result.get_nmethod()->entryPoint());
438 } else {
439 // compiled target
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()) {
446 clear();
447 } else if (result.is_method()) {
448 // don't set to interpreted method -- may be "compiled only" send
449 clear();
450 } else {
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();
463 if (newNM != NULL) {
464 set_call_destination(newNM->entryPoint());
465 } else {
466 clear(); // don't set to interpreted method -- may be "compiled only" send
470 return;
473 // POLYMORPHIC
474 PIC* p = pic();
475 if (p) {
476 nmethod* nm;
477 PIC* result = p->cleanup(&nm);
478 if (result != p) {
479 if (p != NULL) {
480 // still polymorphic
481 set_call_destination(result->entry());
482 } else {
483 if (nm) {
484 // monomorphic
485 set_call_destination(nm->entryPoint());
486 } else {
487 // anamorphic
488 clear();
492 return;
495 // IMPOSSIBLE STATE
496 ShouldNotReachHere();
500 void CompiledIC::print() {
501 ResourceMark rm; // so we can print from debugger
502 lprintf("\t((CompiledIC*)%#x) ", this);
503 if (is_empty()) {
504 lprintf("(empty) ");
505 } else {
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 ");
514 lprintf("\n");
516 lprintf("\t- selector : ");
517 selector()->print_symbol_on();
518 lprintf("\n");
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());
526 } else {
527 lprintf(";\tmethod %#x\n", it.interpreted_method());
529 it.advance();
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");
538 } else {
539 // non-empty icache
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);
554 return iter.ic();
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");
569 return m;
570 } else {
571 return NULL;
576 klassOop CompiledIC::get_klass(int i) const {
577 PIC* p = pic();
578 if (p) {
579 PIC_Iterator it(p);
580 for (int j = 0; j < i; j++) it.advance();
581 return it.get_klass();
582 } else {
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());
598 } else {
599 CompiledIC_Iterator it((CompiledIC*)this);
600 it.goto_elem(i);
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());
631 #else
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) {}
638 #endif