00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 # include "incls/_precompiled.incl"
00026 # include "incls/_stubRoutines.cpp.incl"
00027
00028 const int max_fast_allocate_size = 9;
00029
00030
00031 char* StubRoutines::_ic_normal_lookup_entry = NULL;
00032 char* StubRoutines::_ic_super_lookup_entry = NULL;
00033 char* StubRoutines::_zombie_nmethod_entry = NULL;
00034 char* StubRoutines::_zombie_block_nmethod_entry = NULL;
00035 char* StubRoutines::_megamorphic_ic_entry = NULL;
00036 char* StubRoutines::_compile_block_entry = NULL;
00037 char* StubRoutines::_continue_NLR_entry = NULL;
00038 char* StubRoutines::_call_sync_DLL_entry = NULL;
00039 char* StubRoutines::_call_async_DLL_entry = NULL;
00040 char* StubRoutines::_lookup_sync_DLL_entry = NULL;
00041 char* StubRoutines::_lookup_async_DLL_entry = NULL;
00042 char* StubRoutines::_recompile_stub_entry = NULL;
00043 char* StubRoutines::_used_uncommon_trap_entry = NULL;
00044 char* StubRoutines::_unused_uncommon_trap_entry = NULL;
00045 char* StubRoutines::_verify_context_chain_entry = NULL;
00046 char* StubRoutines::_deoptimize_block_entry = NULL;
00047 char* StubRoutines::_call_inspector_entry = NULL;
00048
00049 char* StubRoutines::_PIC_stub_entries[PIC::max_nof_entries + 1];
00050 char* StubRoutines::_allocate_entries[max_fast_allocate_size + 1];
00051
00052
00053
00054
00055 void StubRoutines::trace_DLL_call_1(dll_func function, oop* last_argument, int nof_arguments) {
00056 if (!TraceDLLCalls) return;
00057 frame f = DeltaProcess::active()->last_frame();
00058 if (f.is_interpreted_frame()) {
00059
00060 methodOop m = f.method();
00061 CodeIterator it(m, m->bci_from(f.hp()));
00062 InterpretedDLL_Cache* cache = it.dll_cache();
00063 assert(cache->entry_point() == function, "inconsistency with InterpretedDLL_Cache");
00064 assert(cache->number_of_arguments() == nof_arguments, "inconsistency with InterpretedDLL_Cache");
00065 cache->print();
00066 } else {
00067
00068 CompiledDLL_Cache* cache = compiledDLL_Cache_from_return_address(f.pc());
00069 assert(cache->entry_point() == function, "inconsistency with CompiledDLL_Cache");
00070 cache->print();
00071 }
00072
00073 int i = 1;
00074 oop* arg_ptr = last_argument + (nof_arguments - 1);
00075 for (i = 1; i <= nof_arguments; i++, arg_ptr--) {
00076 oop arg = *arg_ptr;
00077 std->print("%6d. ", i);
00078 if (arg->is_smi()) {
00079 std->print("smi value = %d\n", ((smiOop)arg)->value());
00080 } else {
00081 std->print("proxy value = 0x%08x (proxy = 0x%08x)\n", ((proxyOop)arg)->get_pointer(), arg);
00082 }
00083 }
00084 }
00085
00086
00087 void StubRoutines::trace_DLL_call_2(int result) {
00088 if (!TraceDLLCalls) return;
00089 std->print(" result = 0x%08x\n", result);
00090 }
00091
00092
00093 void StubRoutines::wrong_DLL_call() {
00094 { ResourceMark rm;
00095 std->print("DLL call error: number of arguments probably wrong\n");
00096 }
00097 if (DeltaProcess::active()->is_scheduler()) {
00098 DeltaProcess::active()->trace_stack();
00099 fatal("DLL error in scheduler");
00100 } else {
00101 DeltaProcess::active()->suspend(::DLL_lookup_error);
00102 }
00103 ShouldNotReachHere();
00104 }
00105
00106
00107
00108
00109 char* StubRoutines::generate_ic_lookup(MacroAssembler* masm, char* lookup_routine_entry) {
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 char* entry_point = masm->pc();
00123 masm->set_last_Delta_frame_after_call();
00124 masm->movl(ebx, Address(esp));
00125 masm->pushl(eax);
00126 masm->pushl(ebx);
00127 masm->pushl(eax);
00128 masm->call(lookup_routine_entry, relocInfo::runtime_call_type);
00129 masm->movl(ebx, eax);
00130 masm->popl(eax);
00131 masm->popl(eax);
00132 masm->popl(eax);
00133 masm->reset_last_Delta_frame();
00134 masm->jmp(ebx);
00135 return entry_point;
00136 }
00137
00138
00139 extern "C" char* icNormalLookup(oop recv, CompiledIC* ic);
00140 extern "C" char* icSuperLookup (oop recv, CompiledIC* ic);
00141 extern "C" char* zombie_nmethod(CompiledIC* ic);
00142
00143 char* StubRoutines::generate_ic_normal_lookup(MacroAssembler* masm) {
00144 return generate_ic_lookup(masm, (char*)icNormalLookup);
00145 }
00146
00147
00148 char* StubRoutines::generate_ic_super_lookup(MacroAssembler* masm) {
00149 return generate_ic_lookup(masm, (char*)icSuperLookup);
00150 }
00151
00152
00153 char* StubRoutines::generate_zombie_nmethod(MacroAssembler* masm) {
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 char* entry_point = masm->pc();
00164 masm->popl(ebx);
00165
00166
00167 masm->set_last_Delta_frame_after_call();
00168 masm->movl(ebx, Address(esp));
00169 masm->pushl(eax);
00170 masm->pushl(ebx);
00171 masm->call((char*)zombie_nmethod, relocInfo::runtime_call_type);
00172 masm->movl(ecx, eax);
00173 masm->popl(ebx);
00174 masm->popl(eax);
00175 masm->popl(ebx);
00176 masm->reset_last_Delta_frame();
00177 masm->jmp(ecx);
00178 return entry_point;
00179 }
00180
00181
00182
00183
00184
00185
00186 static bool validateContextChain(blockClosureOop block) {
00187 assert(block->is_block(), "must be block");
00188 bool is_valid = true;
00189
00190 { contextOop con = block->lexical_scope();
00191
00192 assert(con->is_context(), "expecting a context");
00193
00194 while (true) {
00195 if (con->unoptimized_context() != NULL) {
00196 is_valid = false;
00197 break;
00198 }
00199 if (!con->has_outer_context()) break;
00200 con = con->outer_context();
00201 }
00202 }
00203
00204 if (is_valid) return true;
00205
00206 assert(block->isCompiledBlock(), "we should be in a compiled block");
00207
00208
00209 methodOop method = block->method();
00210 nmethod* nm = block->jump_table_entry()->block_nmethod();
00211
00212 LOG_EVENT1("Deoptimized context in blockClosure -> switch to methodOop 0x%lx", nm);
00213 {
00214 block->set_method(method);
00215 contextOop con = block->lexical_scope();
00216 contextOop un_con = con->unoptimized_context();
00217 if (un_con) {
00218 block->set_lexical_scope(un_con);
00219 } else {
00220 Unimplemented();
00221 }
00222 }
00223 return false;
00224 }
00225
00226 static void deoptimize_context_and_patch_block(blockClosureOop block) {
00227 assert(block->is_block(), "must be block");
00228 assert(block->isCompiledBlock(), "we should be in a compiled block");
00229
00230
00231 methodOop method = block->method();
00232 nmethod* nm = block->jump_table_entry()->block_nmethod();
00233
00234 LOG_EVENT1("Deoptimized context in blockClosure -> switch to methodOop 0x%lx", nm);
00235
00236 contextOop con = block->lexical_scope();
00237 block->set_method(method);
00238 if (method->expectsContext()) {
00239 guarantee(con && con->is_context(), "Optimized context must be present");
00240
00241
00242 contextOop unoptimized_con = con->unoptimized_context();
00243 guarantee(unoptimized_con && unoptimized_con->is_context(), "Unoptimized context must be present");
00244 block->set_lexical_scope(unoptimized_con);
00245 } else {
00246 guarantee(!con->is_context(), "Cannot be a context");
00247 }
00248 }
00249
00250 extern "C" void restart_primitiveValue();
00251
00252 char* StubRoutines::generate_zombie_block_nmethod(MacroAssembler* masm) {
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 char* entry_point = masm->pc();
00263
00264 masm->set_last_Delta_frame_after_call();
00265 masm->pushl(self_reg);
00266 masm->call((char*)deoptimize_context_and_patch_block, relocInfo::runtime_call_type);
00267 masm->movl(ebx, eax);
00268 masm->popl(self_reg);
00269 masm->reset_last_Delta_frame();
00270 masm->addl(esp, 4);
00271 masm->jmp((char*)restart_primitiveValue, relocInfo::runtime_call_type);
00272 return entry_point;
00273 }
00274
00275 extern "C" char* method_entry_point;
00276
00277 char* StubRoutines::generate_megamorphic_ic(MacroAssembler* masm) {
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 Label is_smi, probe_primary_cache, probe_secondary_cache, call_method, is_methodOop, do_lookup;
00288
00289 masm->bind(is_smi);
00290 masm->movl(ecx, Address((int)&smiKlassObj, relocInfo::external_word_type));
00291 masm->jmp(probe_primary_cache);
00292
00293
00294
00295
00296
00297 char* entry_point = masm->pc();
00298 masm->popl(ebx);
00299 masm->test(eax, Mem_Tag);
00300 masm->jcc(Assembler::zero, is_smi);
00301 masm->movl(ecx, Address(eax, memOopDesc::klass_byte_offset()));
00302
00303
00304
00305
00306
00307
00308
00309 masm->bind(probe_primary_cache);
00310 masm->movl(edx, Address(ebx));
00311
00312 masm->movl(edi, ecx);
00313 masm->xorl(edi, edx);
00314 masm->andl(edi, (primary_cache_size - 1) << 4);
00315
00316 masm->cmpl(ecx, Address(edi, lookupCache::primary_cache_address() + 0*oopSize));
00317 masm->jcc(Assembler::notEqual, probe_secondary_cache);
00318 masm->cmpl(edx, Address(edi, lookupCache::primary_cache_address() + 1*oopSize));
00319 masm->jcc(Assembler::notEqual, probe_secondary_cache);
00320 masm->movl(ecx, Address(edi, lookupCache::primary_cache_address() + 2*oopSize));
00321
00322
00323
00324
00325
00326
00327 masm->bind(call_method);
00328 masm->test(ecx, Mem_Tag);
00329 masm->jcc(Assembler::notZero, is_methodOop);
00330 masm->jmp(ecx);
00331
00332
00333 masm->bind(is_methodOop);
00334 masm->xorl(ebx, ebx);
00335 masm->movl(edx, Address(int(&method_entry_point), relocInfo::external_word_type));
00336
00337
00338
00339
00340
00341
00342
00343 masm->jmp(edx);
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 masm->bind(probe_secondary_cache);
00354 masm->andl(edi, (secondary_cache_size - 1) << 4);
00355
00356 masm->cmpl(ecx, Address(edi, lookupCache::secondary_cache_address() + 0*oopSize));
00357 masm->jcc(Assembler::notEqual, do_lookup);
00358 masm->cmpl(edx, Address(edi, lookupCache::secondary_cache_address() + 1*oopSize));
00359 masm->jcc(Assembler::notEqual, do_lookup);
00360 masm->movl(ecx, Address(edi, lookupCache::secondary_cache_address() + 2*oopSize));
00361 masm->jmp(call_method);
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 masm->bind(do_lookup);
00372 masm->set_last_Delta_frame_after_call();
00373 masm->pushl(eax);
00374 masm->pushl(edx);
00375 masm->pushl(ecx);
00376 masm->call((char*)lookupCache::normal_lookup, relocInfo::runtime_call_type);
00377 masm->movl(ecx, eax);
00378 masm->popl(ebx);
00379 masm->popl(ebx);
00380 masm->popl(eax);
00381 masm->reset_last_Delta_frame();
00382 masm->testl(ecx, ecx);
00383 masm->jcc(Assembler::notZero, call_method);
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 masm->hlt();
00395
00396 return entry_point;
00397 }
00398
00399
00400 char* StubRoutines::generate_compile_block(MacroAssembler* masm) {
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 char* entry_point = masm->pc();
00412 masm->set_last_Delta_frame_after_call();
00413 masm->pushl(eax);
00414 masm->pushl(eax);
00415 masm->call((char*)jumpTable::compile_new_block, relocInfo::runtime_call_type);
00416 masm->movl(ebx, eax);
00417 masm->popl(eax);
00418 masm->popl(eax);
00419 masm->reset_last_Delta_frame();
00420 masm->jmp(ebx);
00421 return entry_point;
00422 }
00423
00424
00425 char* StubRoutines::generate_continue_NLR(MacroAssembler* masm) {
00426
00427
00428
00429 Register ret_addr = temp1;
00430 Register offset = temp2;
00431
00432 char* entry_point = masm->pc();
00433 masm->leave();
00434 masm->popl(ret_addr);
00435 masm->movl(offset, Address(ret_addr, IC_Info::info_offset));
00436 if (IC_Info::number_of_flags > 0) {
00437 masm->sarl(offset, IC_Info::number_of_flags);
00438 }
00439 masm->addl(ret_addr, offset);
00440 masm->jmp(ret_addr);
00441 return entry_point;
00442 }
00443
00444
00445 char* StubRoutines::generate_call_DLL(MacroAssembler* masm, bool async) {
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 Label loop_entry, no_arguments, smi_argument, next_argument, wrong_call;
00477
00478 char* entry_point = masm->pc();
00479 masm->set_last_Delta_frame_after_call();
00480 masm->pushl(0);
00481 masm->movl(esi, esp);
00482 masm->pushl(esp);
00483 if (TraceDLLCalls) {
00484 masm->pushl(esi);
00485 masm->pushl(ebx);
00486 masm->pushl(ecx);
00487 masm->pushl(edx);
00488 masm->call((char*)trace_DLL_call_1, relocInfo::runtime_call_type);
00489 masm->popl(edx);
00490 masm->popl(ecx);
00491 masm->popl(ebx);
00492 masm->popl(esi);
00493 }
00494 masm->testl(ebx, ebx);
00495 masm->jcc(MacroAssembler::notZero, loop_entry);
00496
00497
00498 masm->bind(no_arguments);
00499 if (async) {
00500 masm->pushl(edx);
00501 masm->pushl(esi);
00502 masm->call((char*)DLLs::enter_async_call, relocInfo::runtime_call_type);
00503 masm->popl(esi);
00504 masm->popl(edx);
00505 }
00506
00507
00508 masm->call(edx);
00509
00510
00511 masm->popl(ebx);
00512 masm->cmpl(ebx, esp);
00513 masm->jcc(Assembler::notEqual, wrong_call);
00514
00515
00516 masm->movl(ebx, esp);
00517 masm->pushl(eax);
00518 masm->pushl(ebx);
00519 char* exit_dll = (char*)(async ? DLLs::exit_async_call : DLLs::exit_sync_call);
00520 masm->call(exit_dll, relocInfo::runtime_call_type);
00521 masm->popl(ebx);
00522 masm->popl(eax);
00523
00524 if (TraceDLLCalls) {
00525 masm->pushl(eax);
00526 masm->call((char*)trace_DLL_call_2, relocInfo::runtime_call_type);
00527 masm->popl(eax);
00528 }
00529 masm->popl(ebx);
00530 masm->reset_last_Delta_frame();
00531 masm->ret(0);
00532
00533
00534 masm->bind(wrong_call);
00535 masm->call((char*)wrong_DLL_call, relocInfo::runtime_call_type);
00536 masm->hlt();
00537
00538
00539 masm->bind(smi_argument);
00540 masm->sarl(eax, Tag_Size);
00541
00542
00543 masm->bind(next_argument);
00544 masm->pushl(eax);
00545 masm->addl(ecx, oopSize);
00546 masm->decl(ebx);
00547 masm->jcc(MacroAssembler::zero, no_arguments);
00548
00549
00550 masm->bind(loop_entry);
00551
00552
00553 masm->movl(eax, Address(ecx));
00554 masm->testb(eax, Mem_Tag);
00555 masm->jcc(MacroAssembler::zero, smi_argument);
00556
00557
00558 masm->movl(eax, Address(eax, pointer_offset));
00559 masm->jmp(next_argument);
00560
00561 return entry_point;
00562 }
00563
00564
00565 char* StubRoutines::generate_lookup_DLL(MacroAssembler* masm, bool async) {
00566
00567
00568
00569
00570
00571
00572
00573 assert(call_DLL_entry(async) != NULL, "call_DLL_entry must have been generated before");
00574 char* entry_point = masm->pc();
00575 masm->set_last_Delta_frame_after_call();
00576 masm->pushl(ebx);
00577 masm->pushl(ecx);
00578 masm->call((char*)DLLs::lookup_and_patch_CompiledDLL_Cache, relocInfo::runtime_call_type);
00579 masm->popl(ecx);
00580 masm->popl(ebx);
00581 masm->movl(edx, eax);
00582 masm->reset_last_Delta_frame();
00583 masm->jmp(call_DLL_entry(async), relocInfo::runtime_call_type);
00584 return entry_point;
00585 }
00586
00587
00588 char* StubRoutines::generate_recompile_stub(MacroAssembler* masm) {
00589
00590
00591
00592
00593
00594 char* entry_point = masm->pc();
00595
00596 masm->set_last_Delta_frame_after_call();
00597 masm->call((char*)SavedRegisters::save_registers, relocInfo::runtime_call_type);
00598 masm->movl(ebx, Address(esp));
00599 masm->pushl(eax);
00600 masm->pushl(ebx);
00601 masm->pushl(eax);
00602 masm->call((char*)Recompilation::nmethod_invocation_counter_overflow, relocInfo::runtime_call_type);
00603 masm->movl(ecx, eax);
00604 masm->popl(eax);
00605 masm->popl(ebx);
00606 masm->popl(eax);
00607 masm->reset_last_Delta_frame();
00608 masm->leave();
00609 masm->jmp(ecx);
00610 return entry_point;
00611 }
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 char* StubRoutines::generate_uncommon_trap(MacroAssembler* masm) {
00639 char* entry_point = masm->pc();
00640 masm->set_last_Delta_frame_after_call();
00641 masm->call((char*)SavedRegisters::save_registers, relocInfo::runtime_call_type);
00642 masm->call((char*)uncommon_trap, relocInfo::runtime_call_type);
00643 masm->reset_last_Delta_frame();
00644 masm->ret(0);
00645 return entry_point;
00646 }
00647
00648
00649
00650 char* StubRoutines::generate_verify_context_chain(MacroAssembler* masm) {
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666 Label deoptimize;
00667
00668 char* entry_point = masm->pc();
00669 masm->set_last_Delta_frame_after_call();
00670 masm->pushl(self_reg);
00671 masm->call((char*)validateContextChain, relocInfo::runtime_call_type);
00672 masm->movl(ebx, eax);
00673 masm->popl(self_reg);
00674 masm->reset_last_Delta_frame();
00675 masm->testl(ebx,ebx);
00676 masm->jcc(MacroAssembler::zero, deoptimize);
00677 masm->ret(0);
00678
00679 masm->bind(deoptimize);
00680 masm->addl(esp, 4);
00681 masm->jmp((char*)restart_primitiveValue, relocInfo::runtime_call_type);
00682 return entry_point;
00683 }
00684
00685
00686 static blockClosureOop deoptimize_block(blockClosureOop block) {
00687 VerifyNoAllocation vna;
00688 assert(block->is_block(), "must be a block");
00689 assert(block->isCompiledBlock(), "we should be in a compiled block");
00690
00691 #ifdef ASSERT
00692
00693 bool has_unoptimized_context = false;
00694 { contextOop con = block->lexical_scope();
00695
00696 assert(con->is_context(), "expecting a context");
00697 while (true) {
00698 if (con->unoptimized_context() != NULL) {
00699 has_unoptimized_context = true;
00700 break;
00701 }
00702 if (!con->has_outer_context()) break;
00703 con = con->outer_context();
00704 }
00705 }
00706 assert(has_unoptimized_context, "should have an unoptimized context");
00707 #endif
00708
00709 block->deoptimize();
00710 return block;
00711 }
00712
00713
00714 char* StubRoutines::generate_deoptimize_block(MacroAssembler* masm) {
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725 char* entry_point = masm->pc();
00726 masm->set_last_Delta_frame_after_call();
00727 masm->pushl(self_reg);
00728 masm->call((char*)deoptimize_block, relocInfo::runtime_call_type);
00729 masm->popl(ebx);
00730 masm->reset_last_Delta_frame();
00731 masm->jmp((char*)restart_primitiveValue, relocInfo::runtime_call_type);
00732 return entry_point;
00733 }
00734
00735
00736 char* StubRoutines::generate_call_inspector(MacroAssembler* masm) {
00737
00738 char* entry_point = masm->pc();
00739 masm->set_last_Delta_frame_after_call();
00740 masm->pushad();
00741 masm->call((char*)MacroAssembler::inspector, relocInfo::runtime_call_type);
00742 masm->popad();
00743 masm->reset_last_Delta_frame();
00744 masm->ret(0);
00745 return entry_point;
00746 }
00747
00748
00749 char* StubRoutines::generate_PIC_stub(MacroAssembler* masm, int pic_size) {
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 Label found, loop;
00767
00768
00769
00770
00771
00772
00773
00774
00775 masm->bind(found);
00776 masm->movl(edx, Address(int(&method_entry_point), relocInfo::external_word_type));
00777
00778 masm->xorl(ebx, ebx);
00779
00780
00781
00782 masm->jmp(edx);
00783
00784
00785
00786
00787
00788 char* entry_point = masm->pc();
00789 masm->popl(ebx);
00790 masm->movl(edx, Address((int)&smiKlassObj, relocInfo::external_word_type));
00791 masm->test(eax, Mem_Tag);
00792 masm->jcc(Assembler::zero, loop);
00793 masm->movl(edx, Address(eax, memOopDesc::klass_byte_offset()));
00794
00795
00796
00797
00798
00799 masm->bind(loop);
00800 for (int i = 0; i < pic_size; i++) {
00801
00802 masm->cmpl(edx, Address(ebx, i * PIC::PIC_methodOop_entry_size + PIC::PIC_methodOop_klass_offset));
00803 masm->movl(ecx, Address(ebx, i * PIC::PIC_methodOop_entry_size + PIC::PIC_methodOop_offset));
00804 masm->jcc(Assembler::equal, found);
00805 }
00806 assert(ic_normal_lookup_entry() != NULL, "ic_normal_lookup_entry must be generated before");
00807 masm->jmp(ic_normal_lookup_entry(), relocInfo::runtime_call_type);
00808
00809 return entry_point;
00810 }
00811
00812
00813 char* StubRoutines::generate_allocate(MacroAssembler* masm, int size) {
00814 char* entry_point = masm->pc();
00815 masm->hlt();
00816 return entry_point;
00817 }
00818
00819
00820
00821
00822 char* StubRoutines::PIC_stub_entry(int pic_size) {
00823 assert(_is_initialized, "StubRoutines not initialized yet");
00824 assert(1 <= pic_size && pic_size <= PIC::max_nof_entries, "pic size out of range")
00825 return _PIC_stub_entries[pic_size];
00826 }
00827
00828
00829 char* StubRoutines::allocate_entry(int size) {
00830 assert(_is_initialized, "StubRoutines not initialized yet");
00831 assert(0 <= size && size <= max_fast_allocate_size, "size out of range")
00832 return _allocate_entries[size];
00833 }
00834
00835
00836
00837
00838 bool StubRoutines::_is_initialized = false;
00839 char StubRoutines::_code[StubRoutines::_code_size];
00840
00841 char* StubRoutines::generate(MacroAssembler* masm, char* title, char* gen(MacroAssembler*)) {
00842 char* old_pc = masm->pc();
00843 char* entry_point = gen(masm);
00844 char* new_pc = masm->pc();
00845 if (!Disclaimer::is_product() && PrintStubRoutines) {
00846 std->print("Stub routine: %s", title);
00847 std->print(" (%d bytes), entry point = 0x%x\n", new_pc - old_pc, entry_point);
00848 masm->code()->decode();
00849 std->cr();
00850 }
00851 return entry_point;
00852 }
00853
00854
00855 char* StubRoutines::generate(MacroAssembler* masm, char* title, char* gen(MacroAssembler*, int argument), int argument) {
00856 char* old_pc = masm->pc();
00857 char* entry_point = gen(masm, argument);
00858 char* new_pc = masm->pc();
00859 if (!Disclaimer::is_product() && PrintStubRoutines) {
00860 std->print("Stub routine: %s %d", title, argument);
00861 std->print(" (%d bytes), entry point = 0x%x\n", new_pc - old_pc, entry_point);
00862 masm->code()->decode();
00863 std->cr();
00864 }
00865 return entry_point;
00866 }
00867
00868
00869 void StubRoutines::init() {
00870 if (_is_initialized) return;
00871
00872 ResourceMark rm;
00873 CodeBuffer* code = new CodeBuffer(_code, _code_size);
00874 MacroAssembler* masm = new MacroAssembler(code);
00875
00876
00877 _ic_normal_lookup_entry = generate(masm, "ic_normal_lookup", generate_ic_normal_lookup );
00878 _ic_super_lookup_entry = generate(masm, "ic_super_lookup", generate_ic_super_lookup );
00879 _zombie_nmethod_entry = generate(masm, "zombie_nmethod", generate_zombie_nmethod );
00880 _zombie_block_nmethod_entry = generate(masm, "zombie_block_nmethod", generate_zombie_block_nmethod );
00881 _megamorphic_ic_entry = generate(masm, "megamorphic_ic", generate_megamorphic_ic );
00882 _compile_block_entry = generate(masm, "compile_block", generate_compile_block );
00883 _continue_NLR_entry = generate(masm, "continue_NLR", generate_continue_NLR );
00884 _call_sync_DLL_entry = generate(masm, "call_sync_DLL", generate_call_sync_DLL );
00885 _call_async_DLL_entry = generate(masm, "call_async_DLL", generate_call_async_DLL );
00886 _lookup_sync_DLL_entry = generate(masm, "lookup_sync_DLL", generate_lookup_sync_DLL );
00887 _lookup_async_DLL_entry = generate(masm, "lookup_async_DLL", generate_lookup_async_DLL );
00888 _recompile_stub_entry = generate(masm, "recompile_stub", generate_recompile_stub );
00889 _used_uncommon_trap_entry = generate(masm, "used_uncommon_trap", generate_uncommon_trap );
00890 _unused_uncommon_trap_entry = generate(masm, "unused_uncommon_trap", generate_uncommon_trap );
00891 _verify_context_chain_entry = generate(masm, "verify_context_chain", generate_verify_context_chain );
00892 _deoptimize_block_entry = generate(masm, "deoptimize_block", generate_deoptimize_block );
00893 _call_inspector_entry = generate(masm, "call_inspector", generate_call_inspector );
00894
00895 for (int pic_size = 1; pic_size <= PIC::max_nof_entries; pic_size++) {
00896 _PIC_stub_entries[pic_size] = generate(masm, "PIC stub", generate_PIC_stub, pic_size);
00897 }
00898
00899 for (int size = 0; size <= max_fast_allocate_size; size++) {
00900 _allocate_entries[size] = generate(masm, "allocate", generate_allocate, size);
00901 }
00902
00903 masm->finalize();
00904 _is_initialized = true;
00905 if (!Disclaimer::is_product() && PrintStubRoutines) {
00906 std->print("%d bytes generated for stub routines\n", masm->offset());
00907 exit(0);
00908 }
00909 };
00910
00911
00912 void stubRoutines_init() {
00913 StubRoutines::init();
00914 }