00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 # include "incls/_precompiled.incl"
00025
00026 # ifdef DELTA_COMPILER
00027 # include "incls/_compiledIC.cpp.incl"
00028
00029
00030 extern "C" void UncommonTrap() {
00031 ResourceMark rm;
00032 DeltaProcess::active()->trace_stack();
00033 error("Uncommon trap has been executed");
00034 evaluator::read_eval_loop();
00035 }
00036
00037
00038 char* CompiledIC::normalLookupRoutine() {
00039 return StubRoutines::ic_normal_lookup_entry();
00040 }
00041
00042
00043 char* CompiledIC::superLookupRoutine() {
00044 return StubRoutines::ic_super_lookup_entry();
00045 }
00046
00047
00048 extern "C" char* icNormalLookup(oop recv, CompiledIC* ic) {
00049
00050
00051
00052 VerifyNoScavenge vna;
00053 return ic->normalLookup(recv);
00054 }
00055
00056
00057 bool CompiledIC::is_empty() const {
00058 char* d = destination();
00059 return d == normalLookupRoutine() || d == superLookupRoutine();
00060 }
00061
00062
00063 int CompiledIC::ntargets() const {
00064 if (is_empty()) return 0;
00065 PIC* p = pic();
00066 return p != NULL ? p->number_of_targets() : 1;
00067 }
00068
00069
00070 void CompiledIC::set_call_destination(char* entry_point) {
00071
00072 PIC* p = pic();
00073 assert(p == NULL || p->entry() != entry_point, "replacing with same address -- shouldn't dealloc");
00074 if (p != NULL) delete p;
00075 NativeCall::set_destination(entry_point);
00076 }
00077
00078
00079 extern "C" bool have_nlr_through_C;
00080
00081 oop nmethod_substitute() {
00082 return Universe::nilObj();
00083 }
00084
00085
00086 char* CompiledIC::normalLookup(oop recv) {
00087 ResourceMark rm;
00088 char* entry_point;
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 if (Interpreter::contains(begin_addr())) {
00100 std->print_cr("nmethod called from interpreter reports ic miss:");
00101 std->print_cr("interpreter call at: 0x%x", begin_addr());
00102 std->print_cr("nmethod entry point: 0x%x", Interpreter::_last_native_called);
00103 InterpretedIC* ic = as_InterpretedIC(next_instruction_address());
00104 fatal("please notify VM people");
00105 }
00106
00107 if (TraceLookup) {
00108 std->print("CompiledIC lookup (");
00109 recv->klass()->print_value();
00110 std->print(", ");
00111 selector()->print_value();
00112 std->print(")");
00113 std->cr();
00114 }
00115 klassOop klass = recv->klass();
00116 symbolOop sel = selector();
00117 LookupResult result = lookupCache::ic_normal_lookup(klass, sel);
00118
00119 if (result.is_empty()) {
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 BlockScavenge bs;
00130 klassOop msgKlass = klassOop(Universe::find_global("Message"));
00131 oop obj = msgKlass->klass_part()->allocateObject();
00132 assert(obj->is_mem(), "just checkin'...");
00133 memOop msg = memOop(obj);
00134 objArrayOop args = oopFactory::new_objArray(0);
00135
00136
00137
00138
00139
00140 msg->raw_at_put(2, recv);
00141 msg->raw_at_put(3, selector());
00142 msg->raw_at_put(4, args);
00143 symbolOop sel = oopFactory::new_symbol("doesNotUnderstand:");
00144 if (interpreter_normal_lookup(recv->klass(), sel).is_empty()) {
00145
00146 { ResourceMark rm;
00147 std->print("LOOKUP ERROR\n");
00148 sel->print_value(); std->print(" not found\n");
00149 }
00150 if (DeltaProcess::active()->is_scheduler()) {
00151 DeltaProcess::active()->trace_stack();
00152 fatal("lookup error in scheduler");
00153 } else {
00154 DeltaProcess::active()->suspend(::lookup_error);
00155 }
00156 ShouldNotReachHere();
00157 }
00158
00159 oop result = Delta::call(recv, sel, msg);
00160
00161 if (!have_nlr_through_C) {
00162 Unimplemented();
00163 }
00164
00165 return (char*)nmethod_substitute;
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 }
00181
00182 if (isOptimized() && result.is_method()) {
00183
00184 assert(!isMegamorphic(), "megamorphic ICs shouldn't be optimized");
00185 LookupKey key(klass, sel);
00186 VM_OptimizeMethod op(&key, result.method());
00187 VMProcess::execute(&op);
00188 result = lookupCache::ic_normal_lookup(klass, sel);
00189 assert(result.is_entry(), "result must contain a jump table entry");
00190 }
00191
00192 bool empty = is_empty();
00193 if (empty) setDirty();
00194 if (!empty || result.is_method()) {
00195 PIC* pic = PIC::allocate(this, klass, result);
00196 if (pic == NULL) {
00197
00198
00199 assert(!UseMICs, "should return a MIC");
00200 clear();
00201 if (result.is_entry()) {
00202 entry_point = isReceiverStatic()
00203 ? result.entry()->method()->verifiedEntryPoint()
00204 : result.entry()->destination();
00205 } else {
00206 pic = PIC::allocate(this, klass, result);
00207 assert(pic != NULL, "pic must be present");
00208 entry_point = pic->entry();
00209 }
00210 } else {
00211 entry_point = pic->entry();
00212 if (pic->is_megamorphic()) {
00213 setMegamorphic();
00214 }
00215 }
00216 } else {
00217 assert(empty && result.is_entry(), "just checking");
00218
00219
00220 if (TraceLookup2) lprintf("nmethod found, f = 0x%x\n", result.get_nmethod());
00221
00222
00223
00224 entry_point = isReceiverStatic()
00225 ? result.entry()->method()->verifiedEntryPoint()
00226 : result.entry()->destination();
00227 }
00228 assert(isDirty(), "must be dirty now");
00229 if (UseInlineCaching) set_call_destination(entry_point);
00230 if (TraceLookup2) print();
00231 LOG_EVENT3("CompiledICLookup (%#x, %#x) --> %#x", klass, sel, entry_point);
00232 return entry_point;
00233 }
00234
00235
00236 extern "C" char* icSuperLookup(oop recv, CompiledIC* ic) {
00237
00238
00239
00240 VerifyNoScavenge vna;
00241 return ic->superLookup(recv);
00242 }
00243
00244
00245 extern "C" char* zombie_nmethod(char* return_addr) {
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 VerifyNoScavenge vna;
00256 if (Interpreter::contains(return_addr)) {
00257
00258 frame f = DeltaProcess::active()->last_frame();
00259 InterpretedIC* ic = f.current_interpretedIC();
00260 LOG_EVENT1("zombie nmethod called => interpreted IC 0x%x cleared", ic);
00261 ic->cleanup();
00262
00263 f.set_hp(ic->send_code_addr());
00264
00265 return Interpreter::redo_send_entry();
00266 } else {
00267
00268 CompiledIC* ic = CompiledIC_from_return_addr(return_addr);
00269 LOG_EVENT1("zombie nmethod called => compiled IC 0x%x cleaned up", ic);
00270 ic->cleanup();
00271
00272 return ic->begin_addr();
00273 }
00274 }
00275
00276
00277 klassOop CompiledIC::targetKlass() const {
00278 nmethod* nm = target();
00279 if (nm) {
00280 return nm->key.klass();
00281 } else {
00282 Unimplemented(); return NULL;
00283 }
00284 }
00285
00286
00287 klassOop CompiledIC::sending_method_holder() {
00288 char* addr = begin_addr();
00289 nmethod* nm = findNMethod(addr);
00290 PcDesc* pcdesc = nm->containingPcDesc(addr);
00291 ScopeDesc* scope = pcdesc->containingDesc(nm);
00292 return scope->selfKlass()->klass_part()->lookup_method_holder_for(scope->method());
00293 }
00294
00295
00296 char* CompiledIC::superLookup(oop recv) {
00297 ResourceMark rm;
00298 char* entry_point;
00299 assert(!Interpreter::contains(begin_addr()), "should be handled in the interpreter");
00300
00301 klassOop recv_klass = recv->klass();
00302 klassOop mhld_klass = sending_method_holder();
00303 symbolOop sel = selector();
00304
00305 if (TraceLookup) {
00306 std->print("CompiledIC super lookup (");
00307 recv_klass->print_value();
00308 std->print(", ");
00309 mhld_klass->print_value();
00310 std->print(", ");
00311 selector()->print_value();
00312 std->print(")");
00313 std->cr();
00314 }
00315
00316
00317
00318
00319 LookupResult result = lookupCache::ic_super_lookup(recv_klass, mhld_klass->klass_part()->superKlass(), sel);
00320 assert(!result.is_empty(), "lookup cache error");
00321 if (result.is_method()) {
00322
00323 if (TraceLookup2) lprintf("methodOop found, m = 0x%x\n", result.method());
00324
00325
00326 warning("CompiledIC::superLookup didn't find a nmethod - check this");
00327 Unimplemented();
00328 } else {
00329
00330 if (TraceLookup2) lprintf("nmethod %#x found\n", result.get_nmethod());
00331
00332 entry_point = result.entry()->destination();
00333 }
00334 if (UseInlineCaching) set_call_destination(entry_point);
00335 if (TraceLookup2) print();
00336 LOG_EVENT3("SuperLookup (%#x, %#x) --> %#x", recv_klass, sel, entry_point);
00337 return entry_point;
00338 }
00339
00340
00341 bool CompiledIC::is_monomorphic() const {
00342 if (target() != NULL) return true;
00343 PIC* p = pic();
00344 return p != NULL && p->is_monomorphic();
00345 }
00346
00347
00348 bool CompiledIC::is_polymorphic() const {
00349 PIC* p = pic();
00350 return p != NULL && p->is_polymorphic();
00351 }
00352
00353
00354 bool CompiledIC::is_megamorphic() const {
00355 PIC* p = pic();
00356 return p != NULL && p->is_megamorphic();
00357 }
00358
00359
00360 void CompiledIC::replace(nmethod* nm) {
00361 assert(selector() == nm->key.selector(), "mismatched selector");
00362 LOG_EVENT3("compiled IC at 0x%x: new nmethod 0x%x for klass 0x%x replaces old entry", this, nm, nm->key.klass());
00363
00364
00365 if (is_monomorphic()) {
00366 if (pic()) {
00367 assert(pic()->klasses()->at(0) == nm->key.klass(), "mismatched klass");
00368 } else {
00369
00370 assert(findNMethod(destination())->key.equal(&nm->key), "keys must match");
00371 }
00372
00373 set_call_destination(nm->entryPoint());
00374 return;
00375 }
00376
00377 PIC* p = pic();
00378 if (p != NULL) {
00379 PIC* new_pic = p->replace(nm);
00380 if (new_pic != p) {
00381 set_call_destination(new_pic->entry());
00382 }
00383 return;
00384 }
00385
00386 ShouldNotReachHere();
00387 }
00388
00389
00390 void CompiledIC::clear() {
00391
00392 assert(!isSuperSend() || UseNewBackend, "We cannot yet have super sends in nmethods");
00393
00394
00395 set_call_destination(isSuperSend() ? superLookupRoutine() : normalLookupRoutine());
00396
00397
00398
00399
00400 }
00401
00402
00403 void CompiledIC::cleanup() {
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 if (is_empty()) return;
00415
00416
00417 if (is_monomorphic()) {
00418 if (pic()) {
00419
00420 PIC_Iterator it(pic());
00421 assert(it.is_interpreted(), "must be interpreted send in monomorphic case");
00422
00423
00424 if (isSuperSend()) return;
00425 LookupKey key(it.get_klass(), selector());
00426 LookupResult result = lookupCache::lookup(&key);
00427
00428 if (result.matches(it.interpreted_method())) return;
00429
00430 if (result.is_empty()) {
00431 clear();
00432 } else if (result.is_method()) {
00433 it.set_methodOop(result.method());
00434 } else {
00435 assert(result.is_entry(), "lookup result should be a jump table entry");
00436 set_call_destination(result.get_nmethod()->entryPoint());
00437 }
00438 } else {
00439
00440 nmethod* old_nm = findNMethod(destination());
00441 LookupResult result = lookupCache::lookup(&old_nm->key);
00442
00443 if (result.matches(old_nm)) return;
00444
00445 if (result.is_empty()) {
00446 clear();
00447 } else if (result.is_method()) {
00448
00449 clear();
00450 } else {
00451 assert(result.is_entry(), "lookup result should be a jump table entry");
00452 set_call_destination(result.get_nmethod()->entryPoint());
00453 }
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 }
00470 return;
00471 }
00472
00473
00474 PIC* p = pic();
00475 if (p) {
00476 nmethod* nm;
00477 PIC* result = p->cleanup(&nm);
00478 if (result != p) {
00479 if (p != NULL) {
00480
00481 set_call_destination(result->entry());
00482 } else {
00483 if (nm) {
00484
00485 set_call_destination(nm->entryPoint());
00486 } else {
00487
00488 clear();
00489 }
00490 }
00491 }
00492 return;
00493 }
00494
00495
00496 ShouldNotReachHere();
00497 }
00498
00499
00500 void CompiledIC::print() {
00501 ResourceMark rm;
00502 lprintf("\t((CompiledIC*)%#x) ", this);
00503 if (is_empty()) {
00504 lprintf("(empty) ");
00505 } else {
00506 lprintf("(filled: %d targets) ", ntargets());
00507 }
00508 if (isReceiverStatic()) lprintf("static ");
00509 if (isDirty()) lprintf("dirty ");
00510 if (isOptimized()) lprintf("optimized ");
00511 if (isUninlinable()) lprintf("uninlinable ");
00512 if (isSuperSend()) lprintf("super ");
00513 if (isMegamorphic()) lprintf("megamorphic ");
00514 lprintf("\n");
00515
00516 lprintf("\t- selector : ");
00517 selector()->print_symbol_on();
00518 lprintf("\n");
00519
00520 CompiledIC_Iterator it(this);
00521 while (!it.at_end()) {
00522 lprintf("\t- klass : ");
00523 it.klass()->print_value();
00524 if (it.is_compiled()) {
00525 lprintf(";\tnmethod %#x\n", it.compiled_method());
00526 } else {
00527 lprintf(";\tmethod %#x\n", it.interpreted_method());
00528 }
00529 it.advance();
00530 }
00531
00532 lprintf("\t- call address: ");
00533 char* dest = destination();
00534 if (dest == normalLookupRoutine()) {
00535 lprintf("normalLookupRoutine\n");
00536 } else if (dest == superLookupRoutine()) {
00537 lprintf("superLookupRoutine\n");
00538 } else {
00539
00540 lprintf("0x%x\n", destination());
00541 }
00542
00543 lprintf("\t- NLR testcode: 0x%x\n", NLR_testcode());
00544 }
00545
00546
00547 InterpretedIC* CompiledIC::inlineCache() const {
00548
00549 char* addr = begin_addr();
00550 nmethod* nm = findNMethod(addr);
00551 PcDesc* pcdesc = nm->containingPcDesc(addr);
00552 ScopeDesc* scope = pcdesc->containingDesc(nm);
00553 CodeIterator iter = CodeIterator(scope->method(), pcdesc->byteCode);
00554 return iter.ic();
00555 }
00556
00557
00558 symbolOop CompiledIC::selector() const {
00559 return inlineCache()->selector();
00560 }
00561
00562
00563 nmethod* CompiledIC::target() const {
00564 char* dest = destination();
00565 if (Universe::code->contains(dest)) {
00566
00567 nmethod* m = nmethod_from_insts(dest);
00568 assert(m == findNMethod(dest), "wrong nmethod start");
00569 return m;
00570 } else {
00571 return NULL;
00572 }
00573 }
00574
00575
00576 klassOop CompiledIC::get_klass(int i) const {
00577 PIC* p = pic();
00578 if (p) {
00579 PIC_Iterator it(p);
00580 for (int j = 0; j < i; j++) it.advance();
00581 return it.get_klass();
00582 } else {
00583 assert(i == 0, "have max. 1 target method");
00584 return target()->key.klass();
00585 }
00586 }
00587
00588
00589 PIC* CompiledIC::pic() const {
00590 char* dest = destination();
00591 return PIC::find(dest);
00592 }
00593
00594
00595 LookupKey* CompiledIC::key(int i, bool is_normal_send) const {
00596 if (is_normal_send) {
00597 return LookupKey::allocate(get_klass(i), selector());
00598 } else {
00599 CompiledIC_Iterator it((CompiledIC*)this);
00600 it.goto_elem(i);
00601 return LookupKey::allocate(it.klass(), it.interpreted_method());
00602 }
00603 }
00604
00605
00606 bool CompiledIC::wasNeverExecuted() const {
00607 return is_empty() && !isDirty();
00608 }
00609
00610 CompiledIC* CompiledIC_from_return_addr(char* return_addr) {
00611 return (CompiledIC*)nativeCall_from_return_address(return_addr);
00612 }
00613
00614 CompiledIC* CompiledIC_from_relocInfo(char* displacement_address) {
00615 return (CompiledIC*)nativeCall_from_relocInfo(displacement_address);
00616 }
00617
00618 primitive_desc* PrimitiveIC::primitive() {
00619 return primitives::lookup((fntype) destination());
00620 }
00621
00622
00623 char* PrimitiveIC::end_addr() {
00624 primitive_desc* pd = primitive();
00625 int offset = pd->can_perform_NLR() ? IC_Info::instruction_size : 0;
00626 return next_instruction_address() + offset;
00627 }
00628
00629
00630 void PrimitiveIC::print() {
00631 lprintf("\tPrimitive inline cache\n");
00632 primitive_desc* pd = primitive();
00633 lprintf("\t- name : %s\n", pd->name());
00634 if (pd->can_perform_NLR()) {
00635 lprintf("\t- NLR testcode: 0x%x\n", NLR_testcode());
00636 }
00637 }
00638
00639 PrimitiveIC* PrimitiveIC_from_return_addr(char* return_addr) {
00640 return (PrimitiveIC*)nativeCall_from_return_address(return_addr);
00641 }
00642
00643 PrimitiveIC* PrimitiveIC_from_relocInfo(char* displacement_address) {
00644 return (PrimitiveIC*)nativeCall_from_relocInfo(displacement_address);
00645 }
00646
00647 #else
00648
00649
00650 extern "C" void icLookup(int a, int b) {}
00651 extern "C" void icNormalLookup(int a, int b) {}
00652 extern "C" void icSuperLookup(int a, int b) {}
00653
00654 #endif