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
00028 # include "incls/_nmethod.cpp.incl"
00029
00030
00031 void nmFlags::clear() {
00032 assert(sizeof(nmFlags) == sizeof(int), "using more than one word for nmFlags");
00033 *(int*)this = 0;
00034 }
00035
00036
00037 static int instruction_length;
00038 static int location_length;
00039 static int scope_length;
00040 static int nof_noninlined_blocks;
00041
00042
00043 nmethod* new_nmethod(Compiler* c) {
00044
00045
00046 instruction_length = roundTo(c->code()->code_size(), oopSize);
00047 location_length = roundTo(c->code()->reloc_size(), oopSize);
00048 scope_length = roundTo(c->scopeDescRecorder()->size(), oopSize);
00049 nof_noninlined_blocks = c->number_of_noninlined_blocks();
00050 nmethod* nm = new nmethod(c);
00051 if (c->is_method_compile()) {
00052 Universe::code->addToCodeTable(nm);
00053 }
00054 return nm;
00055 }
00056
00057
00058 void* nmethod::operator new(size_t size) {
00059 Unused(size);
00060 assert(sizeof(nmethod) % oopSize == 0, "nmethod size must be multiple of a word");
00061 int nmethod_size = sizeof(nmethod)
00062 + instruction_length
00063 + location_length
00064 + scope_length
00065 + roundTo((nof_noninlined_blocks) * sizeof(uint16), oopSize);
00066 void *p = Universe::code->allocate(nmethod_size);
00067 if (!p) fatal("out of space in code cache");
00068 return p;
00069 }
00070
00071
00072 nmethod::nmethod(Compiler* c) : key(c->key->klass(), c->key->selector_or_method()) {
00073 #ifdef ASSERT
00074
00075 #endif
00076
00077 _instsLen = instruction_length;
00078 _locsLen = location_length;
00079 _scopeLen = scope_length;
00080
00081 main_id = c->main_jumpTable_id;
00082 promoted_id = c->promoted_jumpTable_id;
00083
00084 _number_of_noninlined_blocks = nof_noninlined_blocks;
00085
00086 _invocation_count = 0;
00087 _uncommon_trap_counter = 0;
00088 _number_of_links = 0;
00089
00090 _special_handler_call_offset = theCompiler->special_handler_call_offset();
00091 _entry_point_offset = theCompiler->entry_point_offset();
00092 _verified_entry_point_offset = theCompiler->verified_entry_point_offset();
00093 assert(_entry_point_offset % oopSize == 0, "entry point is not aligned");
00094 assert(_verified_entry_point_offset % oopSize == 0, "verified entry point is not aligned");
00095 assert(0 <= _special_handler_call_offset && _special_handler_call_offset < instruction_length, "bad special handler call offset");
00096 assert(0 <= _entry_point_offset && _entry_point_offset < instruction_length, "bad entry point offset");
00097 assert(0 <= _verified_entry_point_offset && _verified_entry_point_offset < instruction_length, "bad verified entry point offset");
00098
00099 _number_of_float_temporaries = theCompiler->totalNofFloatTemporaries();
00100 _float_section_size = theCompiler->float_section_size();
00101 _float_section_start_offset = theCompiler->float_section_start_offset();
00102
00103 flags.clear();
00104 flags.isUncommonRecompiled = c->is_uncommon_compile();
00105
00106 flags.level = c->level();
00107 flags.version = c->version();
00108 flags.is_block = c->is_block_compile() ? 1 : 0;
00109
00110 flags.state = alive;
00111
00112 if (UseNMethodAging) makeYoung();
00113
00114
00115
00116
00117
00118 c->code()->copyTo(this);
00119
00120 c->scopeDescRecorder()->copyTo(this);
00121
00122 c->copy_noninlined_block_info(this);
00123
00124 flushICacheRange(insts(), instsEnd());
00125 flushICache();
00126
00127 #ifdef ASSERT
00128 check_store();
00129 #endif
00130
00131
00132 if (c->is_method_compile()) {
00133 Universe::code->jump_table()->at(main_id)->set_destination(entryPoint());
00134 } else {
00135 if (has_noninlined_blocks()) {
00136 Universe::code->jump_table()->at(promoted_id)->set_destination(entryPoint());
00137 }
00138 }
00139 if (this == (nmethod*)catchThisOne) warning("caught nmethod");
00140 #ifdef ASSERT
00141
00142
00143 verify_expression_stacks();
00144 #endif
00145 }
00146
00147
00148 nmethod* nmethod::parent() {
00149 if (is_block()) {
00150 int index;
00151 return Universe::code->jump_table()->at(main_id)->parent_nmethod(index);
00152 }
00153 return NULL;
00154 }
00155
00156
00157 nmethod* nmethod::outermost() {
00158 nmethod* p = parent();
00159 if (p == NULL) return this;
00160 return p->outermost();
00161 }
00162
00163
00164 int nmethod::level() const {
00165 assert(flags.level >= 0 && flags.level <= MaxRecompilationLevels,
00166 "invalid level");
00167 return flags.level;
00168 }
00169
00170
00171 jumpTableEntry* nmethod::jump_table_entry() const {
00172 return Universe::code->jump_table()->at(main_id);
00173 }
00174
00175
00176 void nmethod::setVersion(int v) {
00177 assert(v > 0 && v <= MaxVersions, "bad version");
00178 flags.version = v;
00179 }
00180
00181
00182 ScopeDesc* nmethod::containingScopeDesc(char* pc) const {
00183 PcDesc* pcd = containingPcDesc(pc);
00184 if (!pcd) return NULL;
00185 return pcd->containingDesc(this);
00186 }
00187
00188
00189 void nmethod::check_store() {
00190
00191 relocIterator iter(this);
00192 while (iter.next()) {
00193 if (iter.type() == relocInfo::oop_type) {
00194 oop obj = *iter.oop_addr();
00195 if (obj->is_mem() && obj->is_new()) {
00196 fatal("must be tenured oop in compiled code");
00197 }
00198 }
00199 }
00200 }
00201
00202
00203 void nmethod::fix_relocation_at_move(int delta) {
00204 relocIterator iter(this);
00205 while (iter.next()) {
00206 if (iter.is_position_dependent()) {
00207 if (iter.type() == relocInfo::internal_word_type) {
00208 *iter.word_addr() -= delta;
00209 } else {
00210 *iter.word_addr() += delta;
00211 }
00212 }
00213 }
00214 }
00215
00216
00217 methodOop nmethod::method() const {
00218 ResourceMark rm;
00219 return scopes()->root()->method();
00220 }
00221
00222
00223 klassOop nmethod::receiver_klass() const {
00224 ResourceMark rm;
00225 return scopes()->root()->selfKlass();
00226 }
00227
00228
00229 void nmethod::moveTo(void* p, int size) {
00230 # ifdef NOT_IMPLEMENTED
00231 nmethod* to = (nmethod*)p;
00232 if (this == to) return;
00233 if (PrintCodeCompaction) {
00234 printf("*moving nmethod %#lx (", this);
00235 key.print();
00236 printf(") to %#lx\n", to);
00237 fflush(stdout);
00238 }
00239
00240 assert(iabs((char*)to - (char*)this) >= sizeof(NCodeBase),
00241 "nmethods overlap too much");
00242 assert(sizeof(NCodeBase) % oopSize == 0, "should be word-aligned");
00243 copy_oops((oop*)this, (oop*)to, sizeof(NCodeBase) / oopSize);
00244
00245 int delta = (char*) to - (char*) this;
00246
00247 for (relocInfo* q = locs(), *pend = locsEnd(); q < pend; q++) {
00248 bool needShift;
00249 if (q->isIC()) {
00250 IC* sd = q->asIC(this);
00251 sd->shift(delta, this);
00252 needShift = true;
00253 } else {
00254 needShift = true;
00255 }
00256 if (needShift) {
00257 q->shift(this, delta);
00258 }
00259 }
00260
00261 assert(size % oopSize == 0, "not a multiple of oopSize");
00262 copy_oops_overlapping((oop*) this, (oop*) to, size / oopSize);
00263 flushICacheRange(to->insts(), to->instsEnd());
00264 # endif
00265 }
00266
00267
00268 void nmethod::clear_inline_caches() {
00269
00270 relocIterator iter(this);
00271 while (iter.next()) {
00272 if (iter.type() == relocInfo::ic_type) {
00273 iter.ic()->clear();
00274 }
00275 }
00276 }
00277
00278
00279 void nmethod::cleanup_inline_caches() {
00280
00281 if (isZombie()) return;
00282
00283
00284 relocIterator iter(this);
00285 while (iter.next()) {
00286 if (iter.type() == relocInfo::ic_type) {
00287 iter.ic()->cleanup();
00288 }
00289 }
00290 }
00291
00292
00293 void nmethod::makeOld() {
00294 LOG_EVENT1("marking nmethod %#x as old", this);
00295 flags.isYoung = 0;
00296 }
00297
00298
00299 void nmethod::forwardLinkedSends(nmethod* to) {
00300
00301
00302 Unimplemented();
00303 }
00304
00305
00306 void nmethod::unlink() {
00307 LOG_EVENT1("unlinking nmethod %#lx", this);
00308
00309 if (is_method()) {
00310
00311 lookupCache::flush(&key);
00312
00313
00314 if (Universe::code->methodTable->is_present(this)) Universe::code->methodTable->remove(this);
00315 }
00316
00317
00318
00319
00320 }
00321
00322
00323 void nmethod::makeZombie(bool clearInlineCaches) {
00324
00325
00326 if (isZombie()) return;
00327
00328
00329 LOG_EVENT2("%s nmethod 0x%x becomes zombie", (is_method() ? "normal" : "block"), this);
00330 NativeCall* call = nativeCall_at(specialHandlerCall());
00331
00332
00333
00334 if (is_block() && !MakeBlockMethodZombies) return;
00335
00336 if (is_method()) {
00337 call->set_destination(StubRoutines::zombie_nmethod_entry());
00338 } else {
00339 call->set_destination(StubRoutines::zombie_block_nmethod_entry());
00340 }
00341
00342
00343
00344
00345
00346
00347 const char* enter = "\x55\x8b\xec";
00348 char* p = verifiedEntryPoint();
00349 guarantee(p[0] == enter[0] && p[1] == enter[1] && p[2] == enter[2], "not \"push ebp, mov ebp esp\" - check this");
00350
00351 const char nop = '\x90';
00352 const char jmp = '\xeb';
00353 int offset = specialHandlerCall() - &p[3];
00354 guarantee(-128 <= offset && offset < 128, "offset too big for short jump");
00355 p[0] = nop;
00356 p[1] = jmp;
00357 p[2] = char(offset);
00358
00359 if (TraceZombieCreation) {
00360 std->print_cr("%s nmethod 0x%x becomes zombie", (is_method() ? "normal" : "block"), this);
00361 if (WizardMode) {
00362 std->print_cr("entry code sequence:");
00363 char* beg = (char*)min(int(specialHandlerCall()), int(entryPoint()), int(verifiedEntryPoint()));
00364 char* end = (char*)max(int(specialHandlerCall()), int(entryPoint()), int(verifiedEntryPoint()));
00365 Disassembler::decode(beg, end + 10);
00366 }
00367 }
00368
00369
00370 flags.state = zombie;
00371 flags.isToBeRecompiled = 0;
00372 assert(isZombie(), "just checking");
00373
00374
00375 lookupCache::flush(&key);
00376 if (clearInlineCaches) clear_inline_caches();
00377
00378
00379 unlink();
00380 }
00381
00382
00383 bool nmethod::has_noninlined_blocks() const {
00384 return number_of_noninlined_blocks() > 0;
00385 }
00386
00387
00388 int nmethod::number_of_noninlined_blocks() const {
00389 return _number_of_noninlined_blocks;
00390 }
00391
00392
00393 methodOop nmethod::noninlined_block_method_at(int noninlined_block_index) const {
00394 ResourceMark rm;
00395 return noninlined_block_scope_at(noninlined_block_index)->method();
00396 }
00397
00398
00399 inline void nmethod::validate_noninlined_block_scope_index(int index) const {
00400 assert(index > 0,
00401 "noninlined_block_index must be positive");
00402 assert(index <= number_of_noninlined_blocks(),
00403 "noninlined_block_index must be within boundary");
00404 }
00405
00406
00407 NonInlinedBlockScopeDesc* nmethod::noninlined_block_scope_at(int noninlined_block_index) const {
00408 validate_noninlined_block_scope_index(noninlined_block_index);
00409 int offset = noninlined_block_offsets()[noninlined_block_index-1];
00410 return scopes()->noninlined_block_scope_at(offset);
00411 }
00412
00413
00414 void nmethod::noninlined_block_at_put(int noninlined_block_index, int offset) const {
00415 validate_noninlined_block_scope_index(noninlined_block_index);
00416 noninlined_block_offsets()[noninlined_block_index-1] = offset;
00417 }
00418
00419 jumpTableEntry* nmethod::noninlined_block_jumpEntry_at(int noninlined_block_index) const {
00420 validate_noninlined_block_scope_index(noninlined_block_index);
00421 jumpTableID id = is_block() ? promoted_id : main_id;
00422 return Universe::code->jump_table()->at(id.sub(noninlined_block_index));
00423 }
00424
00425 void nmethod::flush() {
00426
00427 EventMarker em("flushing nmethod %#lx %s", this, "");
00428 if (PrintMethodFlushing) {
00429 std->print_cr("*flushing nmethod %#lx", this);
00430 }
00431 if (isZombie()) {
00432 clear_inline_caches();
00433 } else {
00434 makeZombie(true);
00435 }
00436 unlink();
00437 Universe::code->free(this);
00438 }
00439
00440
00441 bool nmethod::depends_on_invalid_klass() {
00442
00443 if (receiver_klass()->is_invalid())
00444 return true;
00445
00446
00447 nmethodScopes* ns = scopes();
00448 for (int index = ns->dependent_length()-1; index >= 0; index--) {
00449 if (ns->dependant_at(index)->is_invalid())
00450 return true;
00451 }
00452
00453
00454 return false;
00455 }
00456
00457
00458 void nmethod::add_family(GrowableArray<nmethod*>* result) {
00459
00460 result->append(this);
00461
00462 int major = is_method() ? main_id.major() : promoted_id.major();
00463
00464 for (int minor = 1; minor <= number_of_noninlined_blocks(); minor++) {
00465 jumpTableEntry* entry = Universe::code->jump_table()->at(jumpTableID(major, minor));
00466 nmethod* bm = entry->block_nmethod();
00467 if (bm) bm->add_family(result);
00468 }
00469 }
00470
00471
00472 GrowableArray<nmethod*>* nmethod::invalidation_family() {
00473 GrowableArray<nmethod*>* result = new GrowableArray<nmethod*>(10);
00474 add_family(result);
00475 return result;
00476 }
00477
00478
00479 PcDesc* nmethod::containingPcDescOrNULL(char* pc, PcDesc* st) const {
00480
00481
00482
00483 assert(contains(pc), "nmethod must contain pc into frame");
00484 int offset = pc - insts();
00485 PcDesc* start = st ? st : pcs();
00486 PcDesc* end = pcsEnd() - 1;
00487
00488
00489 if (start == end) return start;
00490
00491 assert(start <= end, "no PcDescs to search");
00492
00493
00494 PcDesc* middle;
00495 int l = 0, h = end - start;
00496 do {
00497
00498 int m = l + (h - l) / 2;
00499 middle = &start[m];
00500 if (middle->pc < offset) {
00501 l = m + 1;
00502 } else {
00503 h = m - 1;
00504 }
00505 } while (middle->pc != offset && l < h);
00506
00507
00508 while (middle->pc <= offset && middle < end ) middle++;
00509 while (middle->pc > offset && middle > start) middle--;
00510
00511 assert(start <= middle && middle <= end, "should have found a pcDesc");
00512 # ifdef ASSERT
00513 PcDesc* d = st ? st : pcs();
00514 PcDesc* closest = d;
00515 for (; d <= end; d ++) {
00516 if (d->pc <= offset && (closest == NULL || closest->pc <= d->pc)) {
00517 closest = d;
00518 }
00519 }
00520 assert(closest == middle, "found different pcDesc");
00521 # endif
00522
00523 if (middle->pc > offset) {
00524 assert( middle == start, "should be the first PcDesc");
00525
00526 return NULL;
00527 }
00528 return middle;
00529 }
00530
00531
00532
00533 static PcDesc prologue_pd(0, 0, PrologueBCI);
00534
00535 PcDesc* nmethod::containingPcDesc(char* pc, PcDesc* start) const {
00536
00537 PcDesc* p = containingPcDescOrNULL(pc, start);
00538
00539
00540 return p ? p : &prologue_pd;
00541 }
00542
00543
00544 int nmethod::estimatedInvocationCount() const {
00545 Unimplemented();
00546 return 0;
00547 }
00548
00549
00550 static int cmp_addrs(const void* p1, const void* p2) {
00551 char** r1 = (char**) p1;
00552 char** r2 = (char**) p2;
00553 return *r1 - *r2;
00554 }
00555
00556
00557 int nmethod::ncallers() const {
00558 return number_of_links();
00559 }
00560
00561
00562
00563
00564 void nmethod::relocate() {
00565 key.relocate();
00566 scopes()->relocate();
00567 OopNCode::relocate();
00568 }
00569
00570
00571 bool nmethod::switch_pointers(oop from, oop to,
00572 GrowableArray<nmethod*>* nmethods_to_invalidate) {
00573 key.switch_pointers(from, to);
00574 scopes()->switch_pointers(from, to, nmethods_to_invalidate);
00575 check_store();
00576 return OopNCode::switch_pointers(from, to, nmethods_to_invalidate);
00577 }
00578
00579
00580 void nmethod::oops_do(void f(oop*)) {
00581
00582 key.oops_do(f);
00583
00584
00585 relocIterator iter(this);
00586 while (iter.next()) {
00587 if (iter.type() == relocInfo::oop_type) {
00588 f(iter.oop_addr());
00589 }
00590 }
00591
00592
00593 scopes()->oops_do(f);
00594 }
00595
00596
00597 void nmethod::verify() {
00598 ResourceMark rm;
00599
00600 OopNCode::verify2("nmethod");
00601
00602
00603
00604
00605 if (!oop(insts())->is_smi())
00606 error("nmethod at %#lx has unaligned instruction start", this);
00607
00608 if (!oop(entryPoint())->is_smi())
00609 error("nmethod at %#lx has unaligned entryPoint", this);
00610
00611 if (!oop(verifiedEntryPoint())->is_smi())
00612 error("nmethod at %#lx has unaligned verifiedEntryPoint", this);
00613
00614 if (!Universe::code->contains(this))
00615 error("nmethod at %#lx not in zone", this);
00616
00617 scopes()->verify();
00618
00619 for (PcDesc* p = pcs(); p < pcsEnd(); p++) {
00620 if (! p->verify(this)) {
00621 std->print_cr("\t\tin nmethod at %#lx (pcs)", this);
00622 }
00623 }
00624
00625 if (findNMethod((char*) instsEnd() - oopSize) != this) {
00626 error("findNMethod did not find this nmethod (%#lx)", this);
00627 }
00628
00629 verify_expression_stacks();
00630 }
00631
00632
00633 void nmethod::verify_expression_stacks_at(char* pc) {
00634 PcDesc* pd = containingPcDesc(pc);
00635 if (!pd) fatal("PcDesc not found");
00636
00637 ScopeDesc* sd = scopes()->at(pd->scope, pc);
00638 int bci = pd->byteCode;
00639 while (sd) {
00640 sd->verify_expression_stack(bci);
00641 ScopeDesc* next = sd->sender();
00642 if (next) bci = sd->senderBCI();
00643 sd = next;
00644 }
00645 }
00646
00647
00648 void nmethod::verify_expression_stacks() {
00649 relocIterator iter(this);
00650 while (iter.next()) {
00651 switch (iter.type()) {
00652 case relocInfo::ic_type:
00653 verify_expression_stacks_at(iter.ic()->begin_addr());
00654 break;
00655 case relocInfo::prim_type:
00656 if (iter.primIC()->primitive()->can_walk_stack()) {
00657 verify_expression_stacks_at(iter.primIC()->begin_addr());
00658 }
00659 break;
00660 }
00661 }
00662 }
00663
00664
00665 void nmethod::CompiledICs_do(void f(CompiledIC*)) {
00666 relocIterator iter(this);
00667 while (iter.next())
00668 if (iter.type() == relocInfo::ic_type)
00669 f(iter.ic());
00670 }
00671
00672
00673 void nmethod::PrimitiveICs_do(void f(PrimitiveIC*)) {
00674 relocIterator iter(this);
00675 while (iter.next())
00676 if (iter.type() == relocInfo::prim_type)
00677 f(iter.primIC());
00678 }
00679
00680
00681
00682
00683 void nmethod::print() {
00684 ResourceMark rm;
00685 printIndent();
00686 std->print("((nmethod*)%#lx) ", this);
00687 std->print(" for method %#lx ", method());
00688 key.print();
00689 std->print(" { ");
00690 if (isYoung()) std->print("YOUNG ");
00691 if (version()) std->print("v%d ", version());
00692 if (level()) std->print("l%d ", level());
00693 if (isZombie()) std->print("zombie ");
00694 if (isToBeRecompiled()) std->print("TBR ");
00695 if (isUncommonRecompiled()) std->print("UNCOMMON ");
00696 std->print_cr("}:");
00697 Indent ++;
00698
00699 printIndent();
00700 std->print_cr("instructions (%ld bytes): [%#lx..%#lx]", size(), insts(), instsEnd());
00701 printIndent();
00702 std->print_cr("((nmethod*)%#lx)->printCode()", this);
00703
00704
00705 scopes()->print();
00706
00707
00708 Indent --;
00709 }
00710
00711
00712 void nmethod::printCode() {
00713 ResourceMark m;
00714 Disassembler().decode(this);
00715 }
00716
00717
00718 void nmethod::printLocs() {
00719 ResourceMark m;
00720 printIndent();
00721 std->print_cr("locations:");
00722 Indent ++;
00723 relocIterator iter(this);
00724 int last_offset = 0;
00725 for (relocInfo* l = locs(); l < locsEnd(); l++) {
00726 iter.next();
00727 last_offset = l->print(this, last_offset);
00728 if (iter.type() == relocInfo::uncommon_type && iter.wasUncommonTrapExecuted()) std->print(" (taken)");
00729 std->cr();
00730 }
00731 Indent --;
00732 }
00733
00734
00735 void nmethod::printPcs() {
00736 ResourceMark m;
00737 printIndent();
00738 lprintf("pc-bytecode offsets:\n");
00739 Indent ++;
00740 for (PcDesc* p = pcs(); p < pcsEnd(); p ++) p->print(this);
00741 Indent --;
00742 }
00743
00744
00745 void nmethod::print_value_on(outputStream* st) {
00746 st->print("nmethod");
00747 if (WizardMode) st->print(" (0x%lx)", this);
00748 st->print(":");
00749 method()->print_value_for(receiver_klass(), st);
00750 }
00751
00752
00753 static ScopeDesc* print_scope_node(nmethodScopes* scopes, ScopeDesc* sd, int level, outputStream* st, bool with_debug_info) {
00754
00755 st->fill_to(2 + level*2);
00756
00757
00758 sd->print_value_on(st);
00759 st->cr();
00760 if (with_debug_info) sd->print(4 + level*2, UseNewBackend);
00761
00762
00763 ScopeDesc* son = scopes->getNext(sd);
00764 while (son && son->sender_scope_offset() == sd->offset()) {
00765 son = print_scope_node(scopes, son, level+1, st, with_debug_info);
00766 }
00767 return son;
00768 }
00769
00770
00771 void nmethod::print_inlining(outputStream* st, bool with_debug_info) {
00772
00773 ResourceMark rm;
00774 if (st == NULL) st = std;
00775 st->print_cr("nmethod inlining structure");
00776 ScopeDesc* result = print_scope_node(scopes(), scopes()->root(), 0, st, with_debug_info);
00777 if (result != NULL) warning("print_inlining returned prematurely");
00778 }
00779
00780
00781 nmethod* nmethodContaining(char* pc, char* likelyEntryPoint) {
00782 assert(Universe::code->contains(pc), "should contain address");
00783 if (likelyEntryPoint && Universe::code->contains(likelyEntryPoint)) {
00784 nmethod* result = nmethod_from_insts(likelyEntryPoint);
00785 if (result->contains(pc)) return result;
00786 }
00787 return findNMethod(pc);
00788 }
00789
00790
00791 nmethod* findNMethod(void* start) {
00792 nmethod* m = Universe::code->findNMethod(start);
00793 assert(m->encompasses(start), "returned wrong nmethod");
00794 return m;
00795 }
00796
00797
00798 nmethod* findNMethod_maybe(void* start) {
00799 nmethod* m = Universe::code->findNMethod_maybe(start);
00800 assert(!m || m->encompasses(start), "returned wrong nmethod");
00801 return m;
00802 }
00803
00804
00805 inline bool includes(void* p, void* from, void* to) {
00806 return from <= p && p < to;
00807 }
00808
00809
00810 bool nmethod::encompasses(void* p) const {
00811 return includes(p, (void*)this, pcsEnd());
00812 }
00813
00814
00815 #ifdef DEBUG_LATER
00816 PcDesc* nmethod::correspondingPC(ScopeDesc* sd, int bci) {
00817
00818 assert(scopes()->includes(sd), "scope not in this nmethod");
00819 int scope = scopes()->offsetTo(sd);
00820 for (PcDesc* p = pcs(), *end = pcsEnd(); p < end; p ++) {
00821 if (p->scope == scope && p->byteCode == bci) break;
00822 }
00823 if (p < end ) {
00824 return p;
00825 } else {
00826
00827 return NULL;
00828 }
00829 }
00830 #endif
00831
00832
00833 CompiledIC* nmethod::IC_at(char* p) const {
00834 relocIterator iter(this);
00835 while (iter.next())
00836 if (iter.type() == relocInfo::ic_type)
00837 if (iter.ic()->begin_addr() == p) return iter.ic();
00838 return NULL;
00839 }
00840
00841
00842 PrimitiveIC* nmethod::primitiveIC_at(char* p) const {
00843 relocIterator iter(this);
00844 while (iter.next())
00845 if (iter.type() == relocInfo::prim_type)
00846 if (iter.primIC()->begin_addr() == p) return iter.primIC();
00847 return NULL;
00848 }
00849
00850
00851 oop* nmethod::embeddedOop_at(char* p) const {
00852 relocIterator iter(this);
00853 while (iter.next())
00854 if (iter.type() == relocInfo::oop_type)
00855 if (iter.oop_addr() == (oop*) p) return iter.oop_addr();
00856 return NULL;
00857 }
00858
00859
00860 bool nmethod::in_delta_code_at(char* pc) const {
00861 PcDesc* pd = containingPcDescOrNULL(pc);
00862 if (pd == NULL) return false;
00863 return !(pd->byteCode == PrologueBCI || pd->byteCode == EpilogueBCI);
00864 }
00865
00866
00867
00868
00869 void nmethod::overwrite_for_trapping(nmethod_patch* data) {
00870 relocIterator iter(this);
00871 while (iter.next()) {
00872 switch(iter.type()) {
00873 case relocInfo::ic_type: break;
00874 case relocInfo::prim_type: break;
00875 case relocInfo::runtime_call_type: break;
00876 case relocInfo::uncommon_type: break;
00877 }
00878 }
00879 }
00880
00881
00882 void nmethod::restore_from_patch(nmethod_patch* data) {
00883 Unimplemented();
00884 }
00885
00886
00887 void nmethod::print_inlining_database() {
00888 print_inlining_database_on(std);
00889 }
00890
00891
00892 void nmethod::print_inlining_database_on(outputStream* st) {
00893
00894 ResourceMark rm;
00895 RScope* root = RNonDummyScope::constructRScopes(this, false);
00896 GrowableArray<PcDesc*>* uncommon = uncommonBranchList();
00897 root->print_inlining_database_on(st, uncommon);
00898 }
00899
00900
00901 static int compare_pcDescs(PcDesc** a, PcDesc** b) {
00902
00903 int diff = (*a)->scope - (*b)->scope;
00904 return diff ? diff : (*a)->byteCode - (*b)->byteCode;
00905 }
00906
00907
00908 GrowableArray<PcDesc*>* nmethod::uncommonBranchList() {
00909
00910
00911 GrowableArray<PcDesc*>* uncommon = new GrowableArray<PcDesc*>(20);
00912 relocIterator iter(this);
00913 while (iter.next()) {
00914 if (iter.type() == relocInfo::uncommon_type) {
00915 uncommon->append(containingPcDesc((char*)iter.word_addr()));
00916 }
00917 }
00918
00919 uncommon->sort(&compare_pcDescs);
00920 return uncommon;
00921 }
00922
00923
00924 inline void nmethod::decay_invocation_count(double decay_factor) {
00925 double new_count = (double) invocation_count() / decay_factor;
00926 set_invocation_count((int) new_count);
00927 }
00928
00929
00930
00931 void nmethod::sweeper_step(double decay_factor) {
00932
00933 if (isZombie()) return;
00934 decay_invocation_count(decay_factor);
00935 _uncommon_trap_counter = int(_uncommon_trap_counter / decay_factor);
00936 cleanup_inline_caches();
00937 incrementAge();
00938 }
00939
00940
00941 bool nmethod::isYoung() {
00942 if (!UseNMethodAging) return false;
00943 if (!flags.isYoung) return false;
00944
00945 if (age() >= NMethodAgeLimit ||
00946 invocation_count() >= InvocationCounterLimit) {
00947 makeOld();
00948 }
00949 return flags.isYoung;
00950 }
00951
00952
00953 void nmethod_init() {
00954
00955 assert(sizeof(nmFlags) <= 4, "nmFlags occupies more than a word");
00956 }
00957
00958 nmethod* nmethod_from_insts(char* insts) {
00959 nmethod* nm = (nmethod*) insts - 1;
00960 return findNMethod(nm);
00961 }
00962
00963
00964 # endif