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/_compiledPIC.cpp.incl"
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 static const char test_opcode = '\xa8';
00096 static const char call_opcode = '\xe8';
00097 static const char jmp_opcode = '\xe9';
00098 static const uint16 jz_opcode = 0x840f;
00099 static const uint16 mov_opcode = 0x508b;
00100 static const uint16 cmp_opcode = 0xfa81; static const int cmp_opcode_size = sizeof(uint16);
00101
00102
00103
00104 static inline void put_byte(char*& p, u_char b){ *p++ = b; }
00105 static inline void put_shrt(char*& p, uint16 s){ *(uint16*)p = s; p += sizeof(uint16); }
00106 static inline void put_word(char*& p, int w) { *(int*)p = w; p += sizeof(int); }
00107 static inline void put_disp(char*& p, char* d) { put_word(p, (int)(d - p - sizeof(int))); }
00108
00109 static inline int get_shrt(char* p) { return *(uint16*)p; }
00110 static inline char* get_disp(char* p) { return *(int*)p + p + sizeof(int); }
00111
00112
00113
00114 class PIC_contents {
00115 public:
00116
00117 char* smi_nmethod;
00118 methodOop smi_methodOop;
00119
00120
00121 klassOop nmethod_klasses[PIC::max_nof_entries];
00122 char* nmethods[PIC::max_nof_entries];
00123 int n;
00124
00125
00126 klassOop methodOop_klasses[PIC::max_nof_entries];
00127 methodOop methodOops[PIC::max_nof_entries];
00128 int m;
00129
00130 void append_nmethod_entry(klassOop klass, char* entry);
00131 void append_method(klassOop klass, methodOop method);
00132
00133 int number_of_compiled_targets() const { return (smi_nmethod ? 1 : 0) + n; }
00134 int number_of_interpreted_targets() const { return (smi_methodOop ? 1 : 0) + m; }
00135 int number_of_targets() const { return number_of_compiled_targets() + number_of_interpreted_targets(); }
00136
00137 bool has_smi_case() const { return (smi_methodOop != NULL) || (smi_nmethod != NULL); }
00138 bool has_nmethods() const { return (n > 0) || (smi_nmethod != NULL); }
00139
00140
00141 int code_size() const {
00142 int methodOop_size = number_of_interpreted_targets() * PIC::PIC_methodOop_entry_size;
00143 if (has_nmethods()) {
00144 return PIC::PIC_methodOop_entry_offset + n * PIC::PIC_nmethod_entry_size + methodOop_size;
00145 } else {
00146 return PIC::PIC_methodOop_only_offset + methodOop_size;
00147 }
00148 }
00149
00150
00151 PIC_contents() {
00152 smi_nmethod = NULL;
00153 smi_methodOop = NULL;
00154 n = 0;
00155 m = 0;
00156 }
00157 };
00158
00159
00160 void PIC_contents::append_nmethod_entry(klassOop klass, char* entry) {
00161
00162 if (klass == smiKlassObj) {
00163 assert(!has_smi_case(), "cannot overwrite smi case");
00164 smi_nmethod = entry;
00165 } else {
00166 nmethod_klasses[n] = klass;
00167 nmethods[n] = entry;
00168 n++;
00169 }
00170 }
00171
00172
00173 void PIC_contents::append_method(klassOop klass, methodOop method) {
00174
00175 assert(method->is_method(), "must be methodOop");
00176 if (klass == smiKlassObj) {
00177 assert(!has_smi_case(), "cannot overwrite smi case");
00178 smi_methodOop = method;
00179 } else {
00180 methodOop_klasses[m] = klass;
00181 methodOops[m] = method;
00182 m++;
00183 }
00184 }
00185
00186
00187
00188
00189 PIC_Iterator::PIC_Iterator(PIC* pic) {
00190 _pic = pic;
00191 _pos = pic->entry();
00192
00193 if (pic->is_megamorphic()) {
00194
00195 assert(get_disp(_pos + 1) == StubRoutines::megamorphic_ic_entry(), "MIC stub expected");
00196 _state = at_the_end;
00197 } else if (*_pos == call_opcode) {
00198
00199 _state = at_methodOop;
00200 _methodOop_counter = PIC::nof_entries(get_disp(_pos + 1));
00201 _pos += PIC::PIC_methodOop_only_offset;
00202 } else {
00203
00204 char* dest = get_disp(_pos + PIC::PIC_smi_nmethod_offset);
00205 if (dest == CompiledIC::normalLookupRoutine() || _pic->contains(dest)) {
00206
00207 _state = at_nmethod;
00208 _pos += PIC::PIC_nmethod_entry_offset;
00209 } else {
00210
00211 _state = at_smi_nmethod;
00212 }
00213 }
00214 }
00215
00216
00217 void PIC_Iterator::computeNextState() {
00218 if (get_shrt(_pos) == cmp_opcode) {
00219
00220 } else if (*_pos == call_opcode) {
00221 _state = at_methodOop;
00222 _methodOop_counter = PIC::nof_entries(get_disp(_pos + 1));
00223 _pos += PIC::PIC_methodOop_entry_offset - PIC::PIC_nmethod_entry_offset;
00224 } else {
00225 assert(*_pos == jmp_opcode, "jump to lookup routine expected");
00226 _state = at_the_end;
00227 }
00228 }
00229
00230
00231 void PIC_Iterator::advance() {
00232 switch (_state) {
00233 case at_smi_nmethod:
00234 assert(_pos == _pic->entry(), "must be at beginning");
00235 _pos += PIC::PIC_nmethod_entry_offset;
00236 _state = at_nmethod;
00237 computeNextState();
00238 break;
00239 case at_nmethod:
00240 _pos += PIC::PIC_nmethod_entry_size;
00241 computeNextState();
00242 break;
00243 case at_methodOop:
00244 if (--_methodOop_counter > 0) {
00245 _pos += PIC::PIC_methodOop_entry_size;
00246 } else {
00247 _state = at_the_end;
00248 }
00249 break;
00250 case at_the_end:
00251 ShouldNotCallThis();
00252 default:
00253 ShouldNotReachHere();
00254 }
00255 }
00256
00257
00258 klassOop* PIC_Iterator::klass_addr() const {
00259 int offs;
00260 switch (state()) {
00261 case at_smi_nmethod: ShouldNotCallThis();
00262 case at_nmethod : offs = PIC::PIC_nmethod_klass_offset; break;
00263 case at_methodOop : offs = PIC::PIC_methodOop_klass_offset;break;
00264 case at_the_end : ShouldNotCallThis();
00265 default : ShouldNotReachHere();
00266 }
00267 return (klassOop*)(_pos + offs);
00268 }
00269
00270
00271 int* PIC_Iterator::nmethod_disp_addr() const {
00272 int offs;
00273 switch (state()) {
00274 case at_smi_nmethod: offs = PIC::PIC_smi_nmethod_offset; break;
00275 case at_nmethod : offs = PIC::PIC_nmethod_offset; break;
00276 case at_methodOop : ShouldNotCallThis();
00277 case at_the_end : ShouldNotCallThis();
00278 default : ShouldNotReachHere();
00279 }
00280 return (int*)(_pos + offs);
00281 }
00282
00283
00284 methodOop* PIC_Iterator::methodOop_addr() const {
00285 int offs;
00286 switch (state()) {
00287 case at_smi_nmethod: ShouldNotCallThis();
00288 case at_nmethod : ShouldNotCallThis();
00289 case at_methodOop : offs = PIC::PIC_methodOop_offset; break;
00290 case at_the_end : ShouldNotCallThis();
00291 default : ShouldNotReachHere();
00292 }
00293 return (methodOop*)(_pos + offs);
00294 }
00295
00296
00297 void PIC_Iterator::print() {
00298 lprintf("a PIC_Iterator\n");
00299 }
00300
00301
00302
00303
00304 bool PIC::in_heap(char* addr) {
00305 return Universe::code->picHeap->contains(addr);
00306 }
00307
00308
00309 PIC* PIC::find(char* addr) {
00310 if (Universe::code->picHeap->contains(addr)) {
00311 PIC* result = (PIC*)Universe::code->picHeap->findStartOfBlock(addr);
00312 return result;
00313 }
00314 return NULL;
00315 }
00316
00317
00318
00319 klassOop PIC_Iterator::get_klass() const {
00320 return state() == at_smi_nmethod ? smiKlassObj : *klass_addr();
00321 }
00322
00323
00324 char* PIC_Iterator::get_call_addr() const {
00325 int* a = nmethod_disp_addr();
00326 return (char*)a + sizeof(int) + *a;
00327 }
00328
00329
00330 bool PIC_Iterator::is_compiled() const {
00331 switch (state()) {
00332 case at_smi_nmethod: return true;
00333 case at_nmethod : return true;
00334 case at_methodOop : return false;
00335 case at_the_end : ShouldNotCallThis();
00336 default : ShouldNotReachHere();
00337 }
00338 return false;
00339 }
00340
00341
00342 bool PIC_Iterator::is_interpreted() const {
00343 return !is_compiled();
00344 }
00345
00346
00347 nmethod* PIC_Iterator::compiled_method() const {
00348 if (!is_compiled()) return NULL;
00349 return findNMethod(get_call_addr() - sizeof(nmethod));
00350 }
00351
00352
00353 methodOop PIC_Iterator::interpreted_method() const {
00354 if (is_interpreted()) {
00355 return *methodOop_addr();
00356 } else {
00357 return compiled_method()->method();
00358 }
00359 }
00360
00361
00362
00363 void PIC_Iterator::set_klass(klassOop klass) {
00364 assert(state() != at_smi_nmethod, "cannot be set");
00365 *klass_addr() = klass;
00366 }
00367
00368
00369 void PIC_Iterator::set_nmethod(nmethod* nm) {
00370 assert(get_klass() == nm->key.klass(), "mismatched receiver klass");
00371 int* a = nmethod_disp_addr();
00372 *a = nm->verifiedEntryPoint() - (char*)a - sizeof(int);
00373 }
00374
00375
00376 void PIC_Iterator::set_methodOop(methodOop method) {
00377 *methodOop_addr() = method;
00378 }
00379
00380
00381 symbolOop* PIC::MIC_selector_address() const {
00382 assert(is_megamorphic(), "not a MIC");
00383 return (symbolOop*)(entry() + MIC_selector_offset);
00384 }
00385
00386
00387 PIC* PIC::replace(nmethod* nm) {
00388
00389 if (is_megamorphic()) return this;
00390
00391 LOG_EVENT3("compiled PIC at 0x%x: new nmethod 0x%x for klass 0x%x replaces old entry", this, nm, nm->key.klass());
00392
00393 {
00394 PIC_Iterator it(this);
00395 while (it.get_klass() != nm->key.klass()) it.advance();
00396 assert(!it.at_end(), "unexpected end during replace");
00397 if (it.is_compiled()) {
00398 it.set_nmethod(nm);
00399 return this;
00400 }
00401 }
00402
00403 {
00404 PIC_contents contents;
00405 PIC_Iterator it(this);
00406 while (!it.at_end()) {
00407 klassOop receiver_klass = it.get_klass();
00408 if (receiver_klass == nm->key.klass()) {
00409 contents.append_nmethod_entry(nm->key.klass(), nm->verifiedEntryPoint());
00410 } else {
00411 if (it.is_interpreted()) {
00412 contents.append_method(it.get_klass(), it.interpreted_method());
00413 } else {
00414 contents.append_nmethod_entry(it.get_klass(), it.get_call_addr());
00415 }
00416 }
00417 it.advance();
00418 }
00419 int allocated_code_size = contents.code_size();
00420 return new (allocated_code_size) PIC(_ic, &contents, allocated_code_size);
00421 }
00422 }
00423
00424
00425 PIC* PIC::cleanup(nmethod** nm) {
00426
00427 if (is_megamorphic()) return this;
00428
00429 bool pic_layout_has_changed = false;
00430
00431
00432
00433
00434
00435
00436 PIC_contents contents;
00437 PIC_Iterator it(this);
00438 while (!it.at_end()) {
00439 klassOop receiver_klass = it.get_klass();
00440 if (it.is_interpreted()) {
00441
00442 if(compiled_ic()->isSuperSend()) {
00443 contents.append_method(it.get_klass(), it.interpreted_method());
00444 } else {
00445 LookupKey key(it.get_klass(), it.interpreted_method()->selector());
00446 LookupResult result = lookupCache::lookup(&key);
00447 if (result.matches(it.interpreted_method())) {
00448 contents.append_method(it.get_klass(), it.interpreted_method());
00449 } else {
00450 if (result.is_method()) {
00451 contents.append_method(it.get_klass(), result.method());
00452 it.set_methodOop(result.method());
00453 } else if (result.is_entry()) {
00454 contents.append_nmethod_entry(it.get_klass(), result.get_nmethod()->verifiedEntryPoint());
00455 pic_layout_has_changed = true;
00456 } else {
00457 pic_layout_has_changed = true;
00458 }
00459 }
00460 }
00461 } else {
00462
00463 nmethod* nm = it.compiled_method();
00464 LookupResult result = lookupCache::lookup(&nm->key);
00465 if (result.matches(nm)) {
00466 contents.append_nmethod_entry(it.get_klass(), it.get_call_addr());
00467 } else {
00468 if (result.is_method()) {
00469 contents.append_method(it.get_klass(), result.method());
00470 pic_layout_has_changed = true;
00471 } else if (result.is_entry()) {
00472 contents.append_nmethod_entry(it.get_klass(), result.get_nmethod()->verifiedEntryPoint());
00473 it.set_nmethod(result.get_nmethod());
00474 } else {
00475 pic_layout_has_changed = true;
00476 }
00477 }
00478 }
00479 it.advance();
00480 }
00481
00482 *nm = NULL;
00483 if (pic_layout_has_changed) {
00484
00485 if (contents.number_of_targets() == 0) {
00486
00487 return NULL;
00488 }
00489
00490 if (contents.number_of_targets() == 1 && contents.has_nmethods()) {
00491
00492 *nm = findNMethod(contents.has_smi_case() ? contents.smi_nmethod : contents.nmethods[0]);
00493 assert(*nm, "nmethod must be present");
00494 return NULL;
00495 }
00496
00497 int allocated_code_size = contents.code_size();
00498 return new (allocated_code_size) PIC(_ic, &contents, allocated_code_size);
00499 }
00500
00501
00502 return this;
00503 }
00504
00505
00506 int PIC::nof_entries(char* pic_stub) {
00507 int i = 1;
00508 while (true) {
00509 if (pic_stub == StubRoutines::PIC_stub_entry(i)) return i;
00510 i++;
00511 }
00512 ShouldNotReachHere();
00513 return 0;
00514 }
00515
00516
00517 int PIC::code_for_methodOops_only(char* entry, PIC_contents* c) {
00518 char* p = entry;
00519 put_byte(p, call_opcode);
00520 if (c->smi_methodOop == NULL) {
00521
00522 put_disp(p, StubRoutines::PIC_stub_entry(c->m));
00523 assert(entry + PIC_methodOop_only_offset == p, "constant inconsistent");
00524 } else {
00525
00526 put_disp(p, StubRoutines::PIC_stub_entry(1 + c->m));
00527 put_word(p, int(smiKlassObj));
00528 put_word(p, int(c->smi_methodOop));
00529 assert(entry + PIC_methodOop_only_offset + PIC_methodOop_entry_size == p, "constant value inconsistent with code pattern");
00530 }
00531 char* p1 = p;
00532 for (int i = 0; i < c->m; i++) {
00533 assert(c->methodOop_klasses[i] != smiKlassObj, "should not be smiKlassObj");
00534 put_word(p, int(c->methodOop_klasses[i]));
00535 put_word(p, int(c->methodOops[i]));
00536 }
00537 assert(p1 + c->m * PIC_methodOop_entry_size == p, "constant value inconsistent with code pattern");
00538 return p - entry;
00539 }
00540
00541
00542 int PIC::code_for_polymorphic_case(char* entry, PIC_contents* c) {
00543 if (c->has_nmethods()) {
00544
00545
00546 char* p = entry;
00547 char* fixup = NULL;
00548 put_byte(p, test_opcode);
00549 put_byte(p, Mem_Tag);
00550
00551 put_shrt(p, jz_opcode);
00552 if (c->smi_nmethod != NULL) {
00553 assert(c->smi_methodOop == NULL, "can only have one method for smis");
00554 put_disp(p, c->smi_nmethod);
00555 } else if (c->smi_methodOop != NULL) {
00556
00557 fixup = p;
00558 put_disp(p, 0);
00559 } else {
00560
00561 put_disp(p, CompiledIC::normalLookupRoutine());
00562 }
00563
00564
00565 put_shrt(p, mov_opcode);
00566 put_byte(p, memOopDesc::klass_byte_offset());
00567 assert(entry + PIC_nmethod_entry_offset == p, "constant value inconsistent with code pattern");
00568
00569 for (int i = 0; i < c->n; i++) {
00570
00571 assert(c->nmethod_klasses[i] != smiKlassObj, "should not be smiKlassObj");
00572 put_shrt(p, cmp_opcode);
00573 assert(entry + PIC_nmethod_entry_offset + i*PIC_nmethod_entry_size + PIC_nmethod_klass_offset == p, "constant value inconsistent with code pattern");
00574 put_word(p, int(c->nmethod_klasses[i]));
00575
00576 put_shrt(p, jz_opcode);
00577 assert(entry + PIC_nmethod_entry_offset + i*PIC_nmethod_entry_size + PIC_nmethod_offset == p, "constant value inconsistent with code pattern");
00578 put_disp(p, c->nmethods[i]);
00579 }
00580 assert(entry + PIC_nmethod_entry_offset + c->n*PIC_nmethod_entry_size == p, "constant value inconsistent with code pattern");
00581 if (c->smi_methodOop != NULL || c->m > 0) {
00582
00583 if (fixup != NULL) put_disp(fixup, p);
00584 p += code_for_methodOops_only(p, c);
00585 } else {
00586
00587 put_byte(p, jmp_opcode);
00588 put_disp(p, CompiledIC::normalLookupRoutine());
00589 }
00590 return p - entry;
00591 } else {
00592
00593 return code_for_methodOops_only(entry, c);
00594 }
00595 }
00596
00597
00598 int PIC::code_for_megamorphic_case(char* entry) {
00599 char* p = entry;
00600 put_byte(p, call_opcode);
00601 put_disp(p, StubRoutines::megamorphic_ic_entry());
00602 assert(entry + MIC_selector_offset == p, "layout constant inconsistent with code pattern");
00603 put_word(p, int(selector()));
00604 assert(entry + MIC_code_size == p, "layout constant inconsistent with code pattern");
00605 return p - entry;
00606 }
00607
00608
00609 void PIC::shrink_and_generate(PIC* pic, klassOop klass, void* method) {
00610 Unimplemented();
00611 }
00612
00613
00614 void* PIC::operator new(size_t size, int code_size){
00615 return Universe::code->picHeap->allocate(size + code_size);
00616 }
00617
00618
00619 void PIC::operator delete(void* p) {
00620 Universe::code->picHeap->deallocate(p, 0);
00621 }
00622
00623
00624 PIC* PIC::allocate(CompiledIC* ic, klassOop klass, LookupResult result) {
00625 assert(!result.is_empty(), "lookup result cannot be empty");
00626
00627 PIC_contents contents;
00628
00629
00630 if (result.is_entry()) {
00631 contents.append_nmethod_entry(klass, result.get_nmethod()->verifiedEntryPoint());
00632 } else {
00633 contents.append_method(klass, result.method());
00634 }
00635
00636 PIC* old_pic = ic->pic();
00637 nmethod* old_nmethod = ic->target();
00638 bool switch_to_MIC = false;
00639
00640
00641
00642
00643
00644
00645
00646 if (old_pic != NULL) {
00647
00648 assert(old_nmethod == NULL, "just checking");
00649 assert(!old_pic->is_megamorphic(), "MICs should not change anymore");
00650 if (old_pic->number_of_targets() >= max_nof_entries) {
00651 if (UseMICs) {
00652
00653 switch_to_MIC = true;
00654 } else {
00655 ic->resetOptimized();
00656 return NULL;
00657 }
00658 } else {
00659
00660 PIC_Iterator it(old_pic);
00661 while (!it.at_end()) {
00662 if (it.is_interpreted()) {
00663 contents.append_method(it.get_klass(), it.interpreted_method());
00664 } else {
00665 contents.append_nmethod_entry(it.get_klass(), it.get_call_addr());
00666 }
00667 it.advance();
00668 }
00669 }
00670 } else if (old_nmethod != NULL) {
00671
00672 contents.append_nmethod_entry(ic->get_klass(0), old_nmethod->verifiedEntryPoint());
00673 } else {
00674
00675 assert(ic->is_empty(), "just checking");
00676 }
00677
00678 assert(switch_to_MIC ||
00679 contents.number_of_interpreted_targets() > 0 ||
00680 contents.number_of_compiled_targets() > 1,
00681 "no PIC required for only 1 compiled target");
00682
00683 PIC* new_pic = NULL;
00684 if (switch_to_MIC) {
00685 new_pic = new (MIC_code_size) PIC(ic);
00686 } else {
00687 int allocated_code_size = contents.code_size();
00688 new_pic = new (allocated_code_size) PIC(ic, &contents, allocated_code_size);
00689 }
00690
00691 #ifdef ASSERT
00692 new_pic->verify();
00693 #endif
00694
00695 return new_pic;
00696 }
00697
00698
00699
00700 PIC::PIC(CompiledIC* ic, PIC_contents* contents, int allocated_code_size) {
00701 assert(contents->number_of_targets() >= 1, "at least one entry needed for non-megamorphic case");
00702 _ic = ic;
00703 _number_of_targets = contents->number_of_targets();
00704 _code_size = code_for_polymorphic_case(entry(), contents);
00705 assert(code_size() == allocated_code_size, "Please adjust PIC_contents::code_size()");
00706 }
00707
00708
00709 PIC::PIC(CompiledIC* ic) {
00710 _ic = ic;
00711 _number_of_targets = 0;
00712 _code_size = code_for_megamorphic_case(entry());
00713 assert(code_size() == MIC_code_size, "Please adjust PIC_contents::code_size()");
00714 }
00715
00716
00717 GrowableArray<klassOop>* PIC::klasses() const {
00718 GrowableArray<klassOop>* k = new GrowableArray<klassOop>(2);
00719 PIC_Iterator it((PIC*)this);
00720 while(!it.at_end()) {
00721 k->append(it.get_klass());
00722 it.advance();
00723 }
00724 return k;
00725 }
00726
00727
00728 void PIC::oops_do(void f(oop*)) {
00729 if (is_megamorphic()) {
00730
00731 f((oop*)MIC_selector_address());
00732 } else {
00733 PIC_Iterator it(this);
00734 while(!it.at_end()) {
00735 switch(it.state()) {
00736 case PIC_Iterator::at_methodOop: f((oop*) it.methodOop_addr());
00737 case PIC_Iterator::at_nmethod : f((oop*) it.klass_addr());
00738 }
00739 it.advance();
00740 }
00741 }
00742 }
00743
00744
00745 void PIC::print() {
00746 lprintf("\tPIC with %d entr%s\n", number_of_targets(), number_of_targets() == 1 ? "y" : "ies");
00747 lprintf("\t- selector : ");
00748 selector()->print_symbol_on();
00749 lprintf("\n");
00750
00751
00752
00753 int i = 1;
00754 PIC_Iterator it(this);
00755 while (!it.at_end()) {
00756 lprintf("\t- %d. klass : ", i);
00757 it.get_klass()->print_value();
00758 lprintf("\n");
00759 switch (it.state()) {
00760 case PIC_Iterator::at_smi_nmethod:
00761 case PIC_Iterator::at_nmethod : printf("\t- nmethod : %#x (entry %#x)\n",
00762 (int)it.compiled_method(), (int)it.get_call_addr()); break;
00763 case PIC_Iterator::at_methodOop : printf("\t- methodOop: %s\n", it.interpreted_method()->print_value_string()); break;
00764 default: ShouldNotReachHere();
00765 }
00766 i++;
00767 it.advance();
00768 }
00769 }
00770
00771
00772 void PIC::verify() {
00773
00774 ResourceMark rm;
00775 GrowableArray<klassOop>* k = klasses();
00776 for (int i = 0; i < k->length() - 1; i++) {
00777 for (int j = i + 1; j < k->length(); j++) {
00778 if (k->at(i) == k->at(j)) {
00779 std->print("The class ");
00780 k->at(i)->klass_part()->print_name_on(std);
00781 std->print_cr("is twice in PIC 0x%lx", this);
00782 warning("PIC verify error");
00783 }
00784 }
00785 }
00786 }
00787
00788
00789
00790
00791 CompiledIC_Iterator::CompiledIC_Iterator(CompiledIC* ic) {
00792 _ic = ic;
00793 init_iteration();
00794 }
00795
00796
00797 void CompiledIC_Iterator::init_iteration() {
00798 _picit = NULL;
00799 _index = 0;
00800 if (_ic->is_empty()) {
00801 _number_of_targets = 0;
00802 _shape = anamorphic;
00803 } else if (_ic->is_monomorphic()) {
00804 _number_of_targets = 1;
00805 _shape = monomorphic;
00806 PIC* pic = _ic->pic();
00807 if (pic) _picit = new PIC_Iterator(pic);
00808 } else if (_ic->is_polymorphic()) {
00809 PIC* pic = _ic->pic();
00810 _number_of_targets = pic->number_of_targets();
00811 _shape = polymorphic;
00812 _picit = new PIC_Iterator(pic);
00813 } else if (_ic->is_megamorphic()) {
00814 _number_of_targets = 0;
00815 _shape = megamorphic;
00816 } else {
00817 ShouldNotReachHere();
00818 }
00819 }
00820
00821
00822 void CompiledIC_Iterator::advance() {
00823 assert(!at_end(), "iterated over the end");
00824 if (_picit != NULL) {
00825 _picit->advance();
00826 }
00827 _index++;
00828 }
00829
00830
00831 klassOop CompiledIC_Iterator::klass() const {
00832 assert(!at_end(), "iterated over the end");
00833 if (_picit != NULL) {
00834 return _picit->get_klass();
00835 } else {
00836 return _ic->get_klass(0);
00837 }
00838 }
00839
00840
00841 bool CompiledIC_Iterator::is_interpreted() const {
00842 assert(!at_end(), "iterated over the end");
00843 if (_picit != NULL) {
00844 return _picit->is_interpreted();
00845 } else {
00846 return false;
00847 }
00848 }
00849
00850
00851 bool CompiledIC_Iterator::is_compiled() const {
00852 assert(!at_end(), "iterated over the end");
00853 if (_picit != NULL) {
00854 return _picit->is_compiled();
00855 } else {
00856 return true;
00857 }
00858 }
00859
00860
00861 bool CompiledIC_Iterator::is_super_send() const {
00862 extern bool SuperSendsAreAlwaysInlined;
00863 assert(SuperSendsAreAlwaysInlined, "fix this");
00864 return false;
00865 }
00866
00867
00868 methodOop CompiledIC_Iterator::interpreted_method() const {
00869 assert(!at_end(), "iterated over the end");
00870 if (_picit != NULL) {
00871 return _picit->interpreted_method();
00872 } else {
00873 return compiled_method()->method();
00874 }
00875 }
00876
00877
00878 nmethod* CompiledIC_Iterator::compiled_method() const {
00879 assert(!at_end(), "iterated over the end");
00880 if (_picit != NULL) {
00881 return _picit->compiled_method();
00882 } else {
00883 assert(number_of_targets() == 1, "must be monomorphic");
00884 return _ic->target();
00885 }
00886 }
00887
00888
00889 void CompiledIC_Iterator::print() {
00890 lprintf("CompiledIC_Iterator for ((CompiledIC*)%#x) (%s)\n", _ic, selector()->as_string());
00891 }
00892
00893 #endif