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/_interpreter.cpp.incl"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 static const int float_0_offset = oopSize * (frame_temp_offset - 3);
00041 static const int temp_1_offset = oopSize * (frame_temp_offset - 1);
00042 static const int temp_0_offset = oopSize * frame_temp_offset;
00043 static const int esi_offset = oopSize * frame_hp_offset;
00044 static const int self_offset = oopSize * frame_receiver_offset;
00045 static const int link_offset = oopSize * frame_link_offset;
00046 static const int ret_addr_offset= oopSize * frame_return_addr_offset;
00047 static const int arg_n_offset = oopSize * (frame_arg_offset - 1);
00048
00049 static const int max_nof_temps = 256;
00050 static const int max_nof_floats = 256;
00051
00052
00053
00054 bool Interpreter::_is_initialized = false;
00055 char* Interpreter::_code_begin_addr = NULL;
00056 char* Interpreter::_code_end_addr = NULL;
00057 extern "C" interpreter_loop_counter;
00058 extern "C" interpreter_loop_counter_limit;
00059
00060
00061
00062 extern "C" char* interpreter_begin_addr;
00063 extern "C" char* interpreter_end_addr;
00064
00065 bool Interpreter::contains(char* pc) {
00066 return
00067 (interpreter_begin_addr <= pc && pc < interpreter_end_addr) ||
00068 (_code_begin_addr <= pc && pc < _code_end_addr);
00069 }
00070
00071
00072 extern "C" char* InterpreterCodeStatus();
00073
00074 bool Interpreter::is_optimized() { return InterpreterCodeStatus()[0] == 1; }
00075 bool Interpreter::can_trace_bytecodes() { return InterpreterCodeStatus()[1] == 1; }
00076 bool Interpreter::can_trace_sends() { return InterpreterCodeStatus()[2] == 1; }
00077 bool Interpreter::has_assertions() { return InterpreterCodeStatus()[3] == 1; }
00078 bool Interpreter::has_stack_checks() { return InterpreterCodeStatus()[4] == 1; }
00079 bool Interpreter::has_timers() { return InterpreterCodeStatus()[5] == 1; }
00080
00081
00082 void Interpreter::print_code_status() {
00083 if (is_optimized()) {
00084 std->print_cr("- Interpreter code is optimized");
00085 } else {
00086 std->print("- Interpreter code is in debug mode: ");
00087 if (can_trace_bytecodes()) std->print("trace_bytecodes ");
00088 if (can_trace_sends()) std->print("trace_sends ");
00089 if (has_assertions()) std->print("assertions ");
00090 if (has_stack_checks()) std->print("stack_checks ");
00091 if (has_timers()) std->print("timers ");
00092 std->cr();
00093 }
00094 }
00095
00096
00097
00098
00099 extern "C" void loop_counter_overflow() {
00100
00101 Interpreter::loop_counter_overflow();
00102 }
00103
00104
00105 void Interpreter::loop_counter_overflow() {
00106 const bool debug = false;
00107 methodOop method = DeltaProcess::active()->last_frame().method();
00108 method->set_invocation_count(method->invocation_count() + loop_counter_limit());
00109 reset_loop_counter();
00110
00111 if (debug) {
00112 ResourceMark rm;
00113 int l = loop_counter_limit();
00114 std->print("loop counter > %d in ", l);
00115 method->print_value();
00116 std->cr();
00117 }
00118 }
00119
00120
00121 int Interpreter::loop_counter() {
00122 return interpreter_loop_counter;
00123 }
00124
00125
00126 void Interpreter::reset_loop_counter() {
00127 interpreter_loop_counter = 0;
00128 }
00129
00130
00131 int Interpreter::loop_counter_limit() {
00132 return interpreter_loop_counter_limit;
00133 }
00134
00135
00136 void Interpreter::set_loop_counter_limit(int limit) {
00137 assert(0 <= limit, "loop counter limit must be positive");
00138 interpreter_loop_counter_limit = limit;
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148 extern "C" void inline_cache_miss() {
00149 InterpretedIC::inline_cache_miss();
00150 }
00151
00152
00153 extern "C" void verifyPIC(oop pic) {
00154 if (!Universe::is_heap((oop*) pic)) fatal("pic should be in heap");
00155 if (!pic->is_objArray()) fatal("pic should be an objArray");
00156 int length = objArrayOop(pic)->length();
00157 if (!(2*size_of_smallest_interpreterPIC <= length && length <= 2*size_of_largest_interpreterPIC)) fatal("pic has wrong length field");
00158 }
00159
00160
00161 extern "C" void trace_send(oop receiver, methodOop method) {
00162 if (TraceMessageSend) {
00163 ResourceMark rm;
00164 std->print("Trace ");
00165 receiver->print_value();
00166 method->selector()->print_value();
00167 std->cr();
00168 }
00169 }
00170
00171
00172
00173
00174 void Interpreter::trace_bytecode() {
00175 if (TraceBytecodes) {
00176 u_char* ip = DeltaProcess::active()->last_frame().hp();
00177 char* name = Bytecodes::name((Bytecodes::Code)*ip);
00178 std->print("%9d 0x%x: %02x %s\n", NumberOfBytecodesExecuted, ip, *ip, name);
00179 }
00180 }
00181
00182
00183 void Interpreter::wrong_eax() {
00184 fatal("interpreter bug: eax doesn't contain the right value");
00185 }
00186
00187
00188 void Interpreter::wrong_ebx() {
00189 fatal("interpreter bug: high 3 bytes of ebx # 0");
00190 }
00191
00192
00193 void Interpreter::wrong_esp() {
00194 fatal("interpreter bug: esp doesn't contain the right value");
00195 }
00196
00197
00198 void Interpreter::wrong_obj() {
00199 fatal("interpreter bug: register doesn't contain a valid oop");
00200 }
00201
00202
00203 void Interpreter::wrong_primitive_result() {
00204 fatal("interpreter bug: primitive failed that is not supposed to fail");
00205 }
00206
00207
00208 doubleOop Interpreter::oopify_FloatValue() {
00209
00210
00211 frame f = DeltaProcess::active()->last_frame();
00212 assert(*(f.hp() - 3) == Bytecodes::float_unary_op_to_oop && *(f.hp() - 1) == Floats::oopify, "not called by Floats::oopify");
00213 int float_index = *(f.hp() - 2);
00214 assert(0 <= float_index && float_index < max_nof_floats, "illegal float index");
00215 double* float_address = (double*)((char*)f.fp() + (float_0_offset - (max_nof_floats - 1)*floatSize) + float_index*floatSize);
00216 return oopFactory::new_double(*float_address);
00217 }
00218
00219
00220 int* Interpreter::_invocation_counter_addr = NULL;
00221
00222 void Interpreter::set_invocation_counter_limit(int new_limit) {
00223 assert(_invocation_counter_addr != NULL, "invocation counter address unknown");
00224 assert(0 <= new_limit && new_limit <= methodOopDesc::_invocation_count_max, "illegal counter limit");
00225 assert(*((u_char*)_invocation_counter_addr - 2) == 0x81, "not a cmp edx, imm32 instruction anymore?")
00226 *_invocation_counter_addr = new_limit << methodOopDesc::_invocation_count_offset;
00227 }
00228
00229
00230 int Interpreter::get_invocation_counter_limit() {
00231 assert(_invocation_counter_addr != NULL, "invocation counter address unknown");
00232 return get_unsigned_bitfield(*_invocation_counter_addr, methodOopDesc::_invocation_count_offset, methodOopDesc::_invocation_count_width);
00233 }
00234
00235
00236
00237
00238 void Interpreter::init() {
00239 if (_is_initialized) return;
00240 reset_loop_counter();
00241 set_loop_counter_limit(LoopCounterLimit);
00242 set_invocation_counter_limit(InvocationCounterLimit);
00243 _is_initialized = true;
00244 }
00245
00246
00247
00248
00249
00250 class InterpreterGenerator: StackObj {
00251 private:
00252 MacroAssembler* _masm;
00253 bool _debug;
00254
00255 Label _method_entry;
00256 Label _block_entry;
00257 Label _inline_cache_miss;
00258 Label _smi_send_failure;
00259 Label _issue_NLR;
00260 Label _nlr_testpoint;
00261
00262 Label _boolean_expected;
00263 Label _float_expected;
00264 Label _NLR_to_dead_frame;
00265 Label _halted;
00266
00267
00268 void check_ebx();
00269 void check_oop(Register reg);
00270 void should_not_reach_here();
00271
00272
00273 Address arg_addr(int i);
00274 Address arg_addr(Register arg_no);
00275 Address temp_addr(int i);
00276 Address temp_addr(Register temp_no);
00277 Address float_addr(Register float_no);
00278 Address field_addr(Register obj, int i);
00279 Address field_addr(Register obj, Register smi_offset);
00280
00281
00282 void skip_words(int n);
00283 void advance_aligned(int n);
00284
00285 void load_ebx();
00286 void next_ebx();
00287 void jump_ebx();
00288
00289 void load_edi();
00290 void jump_edi();
00291
00292 char* entry_point();
00293
00294
00295 Address self_addr() { return Address(ebp, self_offset); }
00296 Address esi_addr() { return Address(ebp, esi_offset); }
00297 Address context_addr() { return Address(ebp, temp_0_offset); }
00298
00299 void save_esi() { _masm->movl(esi_addr(), esi); }
00300 void restore_esi() { _masm->movl(esi, esi_addr()); }
00301 void restore_ebx() { _masm->xorl(ebx, ebx); }
00302
00303
00304 Address nil_addr() { return Address(int(&nilObj), relocInfo::external_word_type); }
00305 Address true_addr() { return Address(int(&trueObj), relocInfo::external_word_type); }
00306 Address false_addr() { return Address(int(&falseObj), relocInfo::external_word_type); }
00307 Address smiKlass_addr() { return Address(int(&smiKlassObj), relocInfo::external_word_type); }
00308 Address doubleKlass_addr() { return Address(int(&doubleKlassObj), relocInfo::external_word_type); }
00309 Address contextKlass_addr() { return Address(int(&symbolKlassObj), relocInfo::external_word_type); }
00310
00311
00312 void call_C(Label& L);
00313 void call_C(char* entry);
00314 void call_C(Register entry);
00315
00316
00317 void load_recv(Bytecodes::ArgumentSpec arg_spec);
00318 void return_tos(Bytecodes::ArgumentSpec arg_spec);
00319
00320
00321 char* push_temp(int i);
00322 char* push_temp_n();
00323 char* push_arg(int i);
00324 char* push_arg_n();
00325 char* push_smi(bool negative);
00326 char* push_literal();
00327 char* push_tos();
00328 char* push_self();
00329 char* push_const(Address obj_addr);
00330 char* push_global();
00331 char* push_instVar();
00332 char* return_instVar();
00333 char* only_pop();
00334
00335 char* store_temp(int i, bool pop = false);
00336 char* store_temp_n(bool pop = false);
00337 char* store_global(bool pop = false);
00338 char* store_instVar(bool pop = false);
00339
00340 char* allocate_temps(int n);
00341 char* allocate_temps_n();
00342
00343 char* set_self_via_context();
00344 char* push_context_temp(int contextNo, int tempNo);
00345
00346 char* float_allocate();
00347 char* float_floatify();
00348 char* float_oopify();
00349 char* float_move();
00350 char* float_set();
00351 char* float_op(int nof_args, bool returns_float = false);
00352
00353 char* push_closure(char* allocation_routine, bool use_context);
00354 char* install_context(char* allocation_routine, bool for_method);
00355
00356 char* lookup_primitive();
00357 char* call_primitive();
00358 char* call_primitive_can_fail();
00359 char* call_DLL(bool async);
00360
00361 void call_method();
00362 void call_native(Register entry);
00363 void generate_error_handler_code();
00364 void generate_nonlocal_return_code();
00365 void generate_method_entry_code();
00366 void generate_inline_cache_miss_handler();
00367 void generate_predicted_smi_send_failure_handler();
00368 void generate_redo_send_code();
00369 char* normal_send(Bytecodes::Code code, bool allow_methodOop, bool allow_nmethod);
00370
00371 char* interpreted_send(Bytecodes::Code code);
00372 char* compiled_send (Bytecodes::Code code);
00373 char* polymorphic_send(Bytecodes::Code code);
00374 char* megamorphic_send(Bytecodes::Code code);
00375
00376 void check_smi_tags();
00377 char* smi_add();
00378 char* smi_sub();
00379 char* smi_mul();
00380 char* smi_compare_op(Bytecodes::Code code);
00381 char* smi_logical_op(Bytecodes::Code code);
00382 char* smi_shift();
00383
00384 char* objArray_size();
00385 char* objArray_at();
00386 char* objArray_at_put();
00387
00388 char* special_primitive_send_hint();
00389 char* halt();
00390
00391
00392 char* nonlocal_return_tos();
00393 char* nonlocal_return_self();
00394
00395
00396 char* generate_instruction(Bytecodes::Code code);
00397
00398
00399 void info(char* name);
00400
00401
00402 void generate_all();
00403
00404 public:
00405 InterpreterGenerator(CodeBuffer* code, bool debug);
00406 };
00407
00408
00409
00410
00411 void InterpreterGenerator::check_ebx() {
00412
00413 if (_debug) {
00414 Label L;
00415 _masm->testl(ebx, 0xFFFFFF00);
00416 _masm->jcc(Assembler::zero, L);
00417 _masm->call_C((char*)Interpreter::wrong_ebx, relocInfo::runtime_call_type);
00418 _masm->bind(L);
00419 }
00420 }
00421
00422
00423 void InterpreterGenerator::check_oop(Register reg) {
00424
00425 if (_debug) {
00426 Label L;
00427 _masm->testb(reg, Mark_Tag_Bit);
00428 _masm->jcc(Assembler::zero, L);
00429 _masm->call_C((char*)Interpreter::wrong_obj, relocInfo::runtime_call_type);
00430 _masm->bind(L);
00431 }
00432 }
00433
00434
00435 void InterpreterGenerator::should_not_reach_here() {
00436
00437 _masm->hlt();
00438 }
00439
00440
00441
00442
00443 Address InterpreterGenerator::arg_addr(int i) {
00444 assert(1 <= i, "argument number must be positive");
00445 return Address(ebp, arg_n_offset + i*oopSize);
00446 }
00447
00448
00449 Address InterpreterGenerator::arg_addr(Register arg_no) {
00450 return Address(ebp, arg_no, Address::times_4, arg_n_offset + 1*oopSize, relocInfo::none);
00451 }
00452
00453
00454 Address InterpreterGenerator::temp_addr(int i) {
00455 assert(0 <= i, "temporary number must be positive");
00456 return Address(ebp, temp_0_offset - i*oopSize);
00457 }
00458
00459
00460 Address InterpreterGenerator::temp_addr(Register temp_no) {
00461 return Address(ebp, temp_no, Address::times_4, temp_0_offset - (max_nof_temps - 1)*oopSize, relocInfo::none);
00462 }
00463
00464
00465 Address InterpreterGenerator::float_addr(Register float_no) {
00466 return Address(ebp, float_no, Address::times_8, float_0_offset - (max_nof_floats - 1)*floatSize, relocInfo::none);
00467 }
00468
00469
00470 Address InterpreterGenerator::field_addr(Register obj, int i) {
00471 assert(2 <= i, "illegal field offset");
00472 return Address(obj, byteOffset(i));
00473 }
00474
00475
00476 Address InterpreterGenerator::field_addr(Register obj, Register smi_offset) {
00477 return Address(obj, smi_offset, Address::times_1, -Mem_Tag, relocInfo::none);
00478 }
00479
00480
00481
00482
00483 void InterpreterGenerator::skip_words(int n) {
00484 _masm->addl(esi, (n+1)*oopSize);
00485 _masm->andl(esi, -oopSize);
00486 }
00487
00488
00489 void InterpreterGenerator::advance_aligned(int n) {
00490 _masm->addl(esi, n + oopSize - 1);
00491 _masm->andl(esi, -oopSize);
00492 }
00493
00494
00495 void InterpreterGenerator::load_ebx() {
00496 check_ebx();
00497 _masm->movb(ebx, Address(esi));
00498 }
00499
00500
00501 void InterpreterGenerator::next_ebx() {
00502 check_ebx();
00503 _masm->movb(ebx, Address(esi, 1));
00504 _masm->incl(esi);
00505 }
00506
00507
00508 void InterpreterGenerator::jump_ebx() {
00509 if (TraceBytecodes || CountBytecodes || StopInterpreterAt > 0) {
00510 _masm->incl(Address(int(&NumberOfBytecodesExecuted), relocInfo::external_word_type));
00511 if (StopInterpreterAt > 0) {
00512 Label cont;
00513 _masm->cmpl(Address(int(&NumberOfBytecodesExecuted), relocInfo::external_word_type), StopInterpreterAt);
00514 _masm->jcc(Assembler::less, cont);
00515 _masm->int3();
00516 _masm->bind(cont);
00517 }
00518 }
00519 if (TraceBytecodes) {
00520 _masm->pushl(eax);
00521 call_C((char*)Interpreter::trace_bytecode);
00522 _masm->popl(eax);
00523 load_ebx();
00524 }
00525 check_oop(eax);
00526 _masm->jmp(Address(noreg, ebx, Address::times_4, (int)dispatchTable::table()));
00527 }
00528
00529
00530 void InterpreterGenerator::load_edi() {
00531 _masm->movl(edi, Address(noreg, ebx, Address::times_4, (int)dispatchTable::table()));
00532 }
00533
00534
00535 void InterpreterGenerator::jump_edi() {
00536 if (TraceBytecodes || CountBytecodes || StopInterpreterAt > 0) {
00537 _masm->incl(Address(int(&NumberOfBytecodesExecuted), relocInfo::external_word_type));
00538 if (StopInterpreterAt > 0) {
00539 Label cont;
00540 _masm->cmpl(Address(int(&NumberOfBytecodesExecuted), relocInfo::external_word_type), StopInterpreterAt);
00541 _masm->jcc(Assembler::less, cont);
00542 _masm->int3();
00543 _masm->bind(cont);
00544 }
00545 }
00546 if (TraceBytecodes) {
00547 _masm->pushl(eax);
00548 call_C((char*)Interpreter::trace_bytecode);
00549 _masm->popl(eax);
00550 load_ebx();
00551 }
00552 check_oop(eax);
00553 _masm->jmp(edi);
00554 }
00555
00556
00557 char* InterpreterGenerator::entry_point() {
00558 char* ep = _masm->pc();
00559 if (_debug) {
00560 check_ebx();
00561 check_oop(eax);
00562 }
00563 return ep;
00564 }
00565
00566
00567
00568
00569
00570
00571
00572 void InterpreterGenerator::call_C(Label& L) {
00573 save_esi();
00574 _masm->call_C(L, _nlr_testpoint);
00575 restore_esi();
00576 restore_ebx();
00577 }
00578
00579
00580 void InterpreterGenerator::call_C(char* entry) {
00581 save_esi();
00582 _masm->call_C(entry, relocInfo::runtime_call_type, _nlr_testpoint);
00583 restore_esi();
00584 restore_ebx();
00585 }
00586
00587
00588 void InterpreterGenerator::call_C(Register entry) {
00589 save_esi();
00590 _masm->call_C(entry, _nlr_testpoint);
00591 restore_esi();
00592 restore_ebx();
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610 void InterpreterGenerator::load_recv(Bytecodes::ArgumentSpec arg_spec) {
00611 _masm->pushl(eax);
00612 switch (arg_spec) {
00613 case Bytecodes::recv_0_args: break;
00614 case Bytecodes::recv_1_args: _masm->movl(eax, Address(esp, 1*oopSize)); break;
00615 case Bytecodes::recv_2_args: _masm->movl(eax, Address(esp, 2*oopSize)); break;
00616 case Bytecodes::recv_n_args:
00617
00618 _masm->movb(ebx, Address(esi, 1));
00619 _masm->movl(eax, Address(esp, ebx, Address::times_4));
00620 break;
00621 case Bytecodes::args_only : _masm->movl(eax, self_addr()); break;
00622 default : ShouldNotReachHere();
00623 }
00624 }
00625
00626
00627
00628
00629
00630 char* InterpreterGenerator::push_temp(int i) {
00631 char* ep = entry_point();
00632 next_ebx();
00633 _masm->pushl(eax);
00634 load_edi();
00635 _masm->movl(eax, temp_addr(i));
00636 jump_edi();
00637 return ep;
00638 }
00639
00640
00641 char* InterpreterGenerator::push_temp_n() {
00642 char* ep = entry_point();
00643 _masm->addl(esi, 2);
00644 _masm->movb(ebx, Address(esi, -1));
00645 _masm->pushl(eax);
00646 _masm->movl(eax, temp_addr(ebx));
00647 load_ebx();
00648 jump_ebx();
00649 return ep;
00650 }
00651
00652
00653 char* InterpreterGenerator::push_arg(int i) {
00654 char* ep = entry_point();
00655 next_ebx();
00656 _masm->pushl(eax);
00657 load_edi();
00658 _masm->movl(eax, arg_addr(i));
00659 jump_edi();
00660 return ep;
00661 }
00662
00663
00664 char* InterpreterGenerator::push_arg_n() {
00665 char* ep = entry_point();
00666 _masm->addl(esi, 2);
00667 _masm->movb(ebx, Address(esi, -1));
00668 _masm->pushl(eax);
00669 _masm->movl(eax, arg_addr(ebx));
00670 load_ebx();
00671 jump_ebx();
00672 return ep;
00673 }
00674
00675
00676 char* InterpreterGenerator::push_smi(bool negative) {
00677 char* ep = entry_point();
00678 _masm->movb(ebx, Address(esi, 1));
00679 _masm->addl(esi, 2);
00680 _masm->pushl(eax);
00681 if (negative) {
00682 _masm->leal(eax, Address(noreg, ebx, Address::times_4));
00683 _masm->negl(eax);
00684 } else {
00685 _masm->leal(eax, Address(noreg, ebx, Address::times_4, 4, relocInfo::none));
00686 }
00687 load_ebx();
00688 jump_ebx();
00689 return ep;
00690 }
00691
00692
00693 char* InterpreterGenerator::push_literal() {
00694 char* ep = entry_point();
00695 _masm->pushl(eax);
00696 skip_words(1);
00697 load_ebx();
00698 _masm->movl(eax, Address(esi, -4));
00699 jump_ebx();
00700 return ep;
00701 }
00702
00703
00704 char* InterpreterGenerator::push_tos() {
00705 char* ep = entry_point();
00706 next_ebx();
00707 _masm->pushl(eax);
00708 jump_ebx();
00709 return ep;
00710 }
00711
00712
00713 char* InterpreterGenerator::push_self() {
00714 char* ep = entry_point();
00715 next_ebx();
00716 _masm->pushl(eax);
00717 load_edi();
00718 _masm->movl(eax, self_addr());
00719 jump_edi();
00720 return ep;
00721 }
00722
00723
00724 char* InterpreterGenerator::push_const(Address obj_addr) {
00725 char* ep = entry_point();
00726 _masm->pushl(eax);
00727 next_ebx();
00728 _masm->movl(eax, obj_addr);
00729 jump_ebx();
00730 return ep;
00731 }
00732
00733
00734 char* InterpreterGenerator::push_instVar() {
00735 char* ep = entry_point();
00736 advance_aligned(1 + oopSize);
00737 _masm->movl(ecx, self_addr());
00738 _masm->movl(edx, Address(esi, -oopSize));
00739 _masm->pushl(eax);
00740 load_ebx();
00741 _masm->movl(eax, field_addr(ecx, edx));
00742 jump_ebx();
00743 return ep;
00744 }
00745
00746
00747 char* InterpreterGenerator::store_instVar(bool pop) {
00748 char* ep = entry_point();
00749 advance_aligned(1 + oopSize);
00750 _masm->movl(ecx, self_addr());
00751 _masm->movl(edx, Address(esi, -oopSize));
00752 load_ebx();
00753 _masm->movl(field_addr(ecx, edx), eax);
00754 _masm->store_check(ecx, edx);
00755 if (pop) _masm->popl(eax);
00756 jump_ebx();
00757 return ep;
00758 }
00759
00760
00761 char* InterpreterGenerator::return_instVar() {
00762 char* ep = entry_point();
00763 advance_aligned(1 + oopSize);
00764 _masm->movl(ecx, self_addr());
00765 _masm->movl(edx, Address(esi, -oopSize));
00766 _masm->movl(eax, field_addr(ecx, edx));
00767 return_tos(Bytecodes::recv_0_args);
00768 return ep;
00769 }
00770
00771
00772 char* InterpreterGenerator::only_pop() {
00773 char* ep = entry_point();
00774 next_ebx();
00775 _masm->popl(eax);
00776 jump_ebx();
00777 return ep;
00778 }
00779
00780
00781 char* InterpreterGenerator::store_temp(int i, bool pop) {
00782 char* ep = entry_point();
00783 next_ebx();
00784 _masm->movl(temp_addr(i), eax);
00785 if (pop) _masm->popl(eax);
00786 jump_ebx();
00787 return ep;
00788 }
00789
00790
00791 char* InterpreterGenerator::store_temp_n(bool pop) {
00792 char* ep = entry_point();
00793 _masm->addl(esi, 2);
00794 _masm->movb(ebx, Address(esi, -1));
00795 _masm->movl(temp_addr(ebx), eax);
00796 load_ebx();
00797 if (pop) _masm->popl(eax);
00798 jump_ebx();
00799 return ep;
00800 }
00801
00802
00803 char* InterpreterGenerator::push_global() {
00804 char* ep = entry_point();
00805 skip_words(1);
00806 _masm->pushl(eax);
00807 _masm->movl(ecx, Address(esi, -oopSize));
00808 load_ebx();
00809 _masm->movl(eax, field_addr(ecx, associationOopDesc::value_offset()));
00810 jump_ebx();
00811 return ep;
00812 }
00813
00814
00815 char* InterpreterGenerator::store_global(bool pop) {
00816 char* ep = entry_point();
00817 skip_words(1);
00818 _masm->movl(ecx, Address(esi, -oopSize));
00819 load_ebx();
00820 _masm->movl(field_addr(ecx, associationOopDesc::value_offset()), eax);
00821 _masm->store_check(ecx, edx);
00822 if (pop) _masm->popl(eax);
00823 jump_ebx();
00824 return ep;
00825 }
00826
00827
00828 char* InterpreterGenerator::allocate_temps(int n) {
00829 char* ep = entry_point();
00830 assert(n > 0, "just checkin'");
00831 next_ebx();
00832 _masm->pushl(eax);
00833 _masm->movl(eax, nil_addr());
00834 while (--n > 0) _masm->pushl(eax);
00835 jump_ebx();
00836 return ep;
00837 }
00838
00839
00840 char* InterpreterGenerator::allocate_temps_n() {
00841 Label entry, loop;
00842
00843 _masm->bind(loop);
00844 _masm->pushl(eax);
00845 _masm->bind(entry);
00846 _masm->decb(ebx);
00847 _masm->jcc(Assembler::notZero, loop);
00848 load_ebx();
00849 jump_ebx();
00850
00851 char* ep = entry_point();
00852 _masm->movb(ebx, Address(esi, 1));
00853 _masm->addl(esi, 2);
00854 _masm->pushl(eax);
00855 _masm->movl(eax, nil_addr());
00856 _masm->jmp(entry);
00857
00858 return ep;
00859 }
00860
00861
00862
00863
00864
00865
00866
00867 char* InterpreterGenerator::set_self_via_context() {
00868 Label loop;
00869 char* ep = entry_point();
00870 next_ebx();
00871 _masm->movl(edx, self_addr());
00872 _masm->bind(loop);
00873 _masm->movl(ecx, edx);
00874 _masm->movl(edx, Address(edx, contextOopDesc::parent_byte_offset()));
00875 _masm->test(edx, Mem_Tag);
00876 _masm->jcc(Assembler::notZero, loop);
00877 _masm->movl(edx, Address(ecx, contextOopDesc::temp0_byte_offset()));
00878 _masm->movl(self_addr(), edx);
00879 jump_ebx();
00880 return ep;
00881 }
00882
00883
00884 char* InterpreterGenerator::push_context_temp(int contextNo, int tempNo) {
00885 assert(contextNo >= 0, "illegal context no.");
00886 assert(tempNo >= 0, "illegal temporary no.");
00887 char* ep = entry_point();
00888 _masm->pushl(eax);
00889 _masm->movl(ecx, context_addr());
00890 next_ebx();
00891 for (int i = 0; i < contextNo; i++) _masm->movl(ecx, Address(ecx, contextOopDesc::parent_byte_offset()));
00892 _masm->movl(eax, Address(ecx, contextOopDesc::temp0_byte_offset() + tempNo*oopSize));
00893 jump_ebx();
00894 return ep;
00895 }
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908 extern "C" oop allocateBlock(smiOop nofArgs);
00909
00910
00911 extern "C" oop allocateBlock0();
00912 extern "C" oop allocateBlock1();
00913 extern "C" oop allocateBlock2();
00914
00915
00916 char* InterpreterGenerator::push_closure(char* allocation_routine, bool use_context) {
00917 char* ep = entry_point();
00918 _masm->pushl(eax);
00919 if (allocation_routine == (char*)allocateBlock) {
00920
00921 _masm->movb(ebx, Address(esi, 1));
00922 advance_aligned(2 + oopSize);
00923 _masm->shll(ebx, Tag_Size);
00924 save_esi();
00925 _masm->pushl(ebx);
00926 _masm->set_last_Delta_frame_before_call();
00927 _masm->call((char*)allocateBlock, relocInfo::runtime_call_type);
00928 _masm->reset_last_Delta_frame();
00929 _masm->popl(ebx);
00930 } else {
00931
00932 advance_aligned(1 + oopSize);
00933 save_esi();
00934 _masm->call(allocation_routine, relocInfo::runtime_call_type);
00935 }
00936 restore_esi();
00937 _masm->movl(ecx, Address(esi, -oopSize));
00938 if (use_context) {
00939 _masm->movl(edx, context_addr());
00940 if (_debug) {
00941
00942
00943
00944 }
00945 } else {
00946 _masm->popl(edx);
00947 }
00948
00949
00950
00951
00952
00953
00954 _masm->movl(ebx, Address(ecx, methodOopDesc::selector_or_method_byte_offset()));
00955 _masm->movl(Address(eax, blockClosureOopDesc::method_or_entry_byte_offset()), ecx);
00956 _masm->movl(ecx, Address(ebx, methodOopDesc::counters_byte_offset()));
00957 _masm->movl(Address(eax, blockClosureOopDesc::context_byte_offset()), edx);
00958 _masm->addl(ecx, 1 << methodOopDesc::_invocation_count_offset);
00959 _masm->movl(edx, eax);
00960 _masm->movl(Address(ebx, methodOopDesc::counters_byte_offset()), ecx);
00961 restore_ebx();
00962 load_ebx();
00963 _masm->store_check(edx, ecx);
00964 jump_ebx();
00965 return ep;
00966 }
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 extern "C" oop allocateContext(smiOop nofVars);
00980 extern "C" oop allocateContext0();
00981 extern "C" oop allocateContext1();
00982 extern "C" oop allocateContext2();
00983
00984 char* InterpreterGenerator::install_context(char* allocation_routine, bool for_method) {
00985 char* ep = entry_point();
00986 _masm->pushl(eax);
00987 if (allocation_routine == (char*)allocateContext) {
00988
00989 _masm->movb(ebx, Address(esi, 1));
00990 _masm->addl(esi, 2);
00991 _masm->shll(ebx, Tag_Size);
00992 save_esi();
00993 _masm->pushl(ebx);
00994 _masm->call((char*)allocateContext, relocInfo::runtime_call_type);
00995 _masm->popl(ebx);
00996 } else {
00997
00998 _masm->incl(esi);
00999 save_esi();
01000 _masm->call(allocation_routine, relocInfo::runtime_call_type);
01001 }
01002 restore_esi();
01003 restore_ebx();
01004 if (for_method) {
01005 _masm->movl(Address(eax, contextOopDesc::parent_byte_offset()), ebp);
01006 } else {
01007 _masm->movl(ecx, context_addr());
01008 if (_debug) {
01009
01010
01011
01012 }
01013 _masm->movl(Address(eax, contextOopDesc::parent_byte_offset()), ecx);
01014 }
01015 load_ebx();
01016 _masm->movl(context_addr(), eax);
01017 _masm->store_check(eax, ecx);
01018 _masm->popl(eax);
01019 jump_ebx();
01020 return ep;
01021 }
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059 char* InterpreterGenerator::float_allocate() {
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069 Label tLoop, tDone, fLoop, fDone;
01070 assert(oop(Floats::magic)->is_smi(), "must be a smi");
01071 char* ep = entry_point();
01072 if (_debug) {
01073
01074 Label L1, L2;
01075
01076 _masm->leal(ecx, Address(ebp, esi_offset));
01077 _masm->cmpl(esp, ecx);
01078 _masm->jcc(Assembler::equal, L1);
01079 _masm->call_C((char*)Interpreter::wrong_esp, relocInfo::runtime_call_type);
01080 should_not_reach_here();
01081 _masm->bind(L1);
01082
01083
01084 _masm->cmpl(eax, nil_addr());
01085 _masm->jcc(Assembler::equal, L2);
01086 _masm->call_C((char*)Interpreter::wrong_eax, relocInfo::runtime_call_type);
01087 should_not_reach_here();
01088 _masm->bind(L2);
01089 }
01090 _masm->addl(esi, 4);
01091 _masm->pushl(eax);
01092 _masm->pushl(Floats::magic);
01093
01094
01095 _masm->movb(ebx, Address(esi, -3));
01096 _masm->testl(ebx, ebx);
01097 _masm->jcc(Assembler::zero, tDone);
01098 _masm->movl(eax, nil_addr());
01099 _masm->bind(tLoop);
01100 _masm->pushl(eax);
01101 _masm->pushl(eax);
01102 _masm->decl(ebx);
01103 _masm->jcc(Assembler::notZero, tLoop);
01104 _masm->bind(tDone);
01105
01106
01107 _masm->movb(ebx, Address(esi, -2));
01108 _masm->testl(ebx, ebx);
01109 _masm->jcc(Assembler::zero, fDone);
01110 _masm->xorl(eax, eax);
01111 _masm->bind(fLoop);
01112 _masm->pushl(eax);
01113 _masm->pushl(eax);
01114 _masm->decb(ebx);
01115 _masm->jcc(Assembler::notZero, fLoop);
01116 _masm->bind(fDone);
01117
01118
01119 assert(floatSize == 8, "change the constant for shhl below");
01120 _masm->movb(ebx, Address(esi, -1));
01121 _masm->shll(ebx, 3);
01122 _masm->subl(esp, ebx);
01123 restore_ebx();
01124
01125
01126 load_ebx();
01127 _masm->popl(eax);
01128 jump_ebx();
01129
01130 return ep;
01131 }
01132
01133
01134 char* InterpreterGenerator::float_floatify() {
01135 Label is_smi;
01136 char* ep = entry_point();
01137 _masm->addl(esi, 2);
01138 _masm->testb(eax, Mem_Tag);
01139 _masm->jcc(Assembler::zero, is_smi);
01140 _masm->movl(ecx, Address(eax, memOopDesc::klass_byte_offset()));
01141 _masm->cmpl(ecx, doubleKlass_addr());
01142 _masm->jcc(Assembler::notEqual, _float_expected);
01143
01144
01145 _masm->movb(ebx, Address(esi, -1));
01146 _masm->fld_d(Address(eax, byteOffset(doubleOopDesc::value_offset())));
01147 _masm->fstp_d(float_addr(ebx));
01148 load_ebx();
01149 _masm->popl(eax);
01150 jump_ebx();
01151
01152
01153 _masm->bind(is_smi);
01154 _masm->movb(ebx, Address(esi, -1));
01155 _masm->leal(ecx, float_addr(ebx));
01156 _masm->sarl(eax, Tag_Size);
01157 _masm->movl(Address(ecx), eax);
01158 _masm->fild_s(Address(ecx));
01159 _masm->fstp_d(Address(ecx));
01160 load_ebx();
01161 _masm->popl(eax);
01162 jump_ebx();
01163
01164 return ep;
01165 }
01166
01167
01168 char* InterpreterGenerator::float_oopify() {
01169
01170
01171
01172
01173 char* ep = entry_point();
01174
01175
01176 _masm->popl(eax);
01177 _masm->fpop();
01178 call_C((char*)Interpreter::oopify_FloatValue);
01179 load_ebx();
01180 jump_ebx();
01181 return ep;
01182 }
01183
01184
01185 char* InterpreterGenerator::float_move() {
01186 char* ep = entry_point();
01187 _masm->pushl(eax);
01188 _masm->addl(esi, 3);
01189 _masm->xorl(ecx, ecx);
01190 _masm->movb(ebx, Address(esi, -1));
01191 _masm->movb(ecx, Address(esi, -2));
01192 _masm->fld_d(float_addr(ebx));
01193 load_ebx();
01194 _masm->fstp_d(float_addr(ecx));
01195 _masm->popl(eax);
01196 jump_ebx();
01197 return ep;
01198 }
01199
01200
01201 char* InterpreterGenerator::float_set() {
01202 char* ep = entry_point();
01203 _masm->pushl(eax);
01204 _masm->movb(ebx, Address(esi, 1));
01205 advance_aligned(2 + oopSize);
01206 _masm->movl(ecx, Address(esi, -oopSize));
01207 _masm->fld_d(Address(ecx, byteOffset(doubleOopDesc::value_offset())));
01208 _masm->fstp_d(float_addr(ebx));
01209 load_ebx();
01210 _masm->popl(eax);
01211 jump_ebx();
01212 return ep;
01213 }
01214
01215
01216 char* InterpreterGenerator::float_op(int nof_args, bool returns_float) {
01217 assert(0 <= nof_args && nof_args <= 8, "illegal nof_args specification");
01218 char* ep = entry_point();
01219 _masm->pushl(eax);
01220 _masm->addl(esi, 3);
01221 _masm->movb(ebx, Address(esi, -2));
01222 _masm->leal(edx, float_addr(ebx));
01223 _masm->movb(ebx, Address(esi, -1));
01224 _masm->movl(ecx, Address(noreg, ebx, Address::times_4, int(Floats::_function_table), relocInfo::external_word_type));
01225 for (int i = 0; i < nof_args; i++) _masm->fld_d(Address(edx, -i*floatSize));
01226 _masm->call(ecx);
01227 load_ebx();
01228 if (returns_float) {
01229 _masm->fstp_d(Address(edx));
01230 _masm->popl(eax);
01231 }
01232 jump_ebx();
01233 return ep;
01234 }
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245 char* InterpreterGenerator::lookup_primitive() {
01246 char* ep = entry_point();
01247 _masm->pushl(eax);
01248 call_C((char*)primitives::lookup_and_patch);
01249 load_ebx();
01250 _masm->popl(eax);
01251 jump_ebx();
01252 return ep;
01253 }
01254
01255
01256 char* InterpreterGenerator::call_primitive() {
01257 char* ep = entry_point();
01258 advance_aligned(1 + oopSize);
01259 _masm->pushl(eax);
01260 _masm->movl(eax, Address(esi, -oopSize));
01261 call_C(eax);
01262 if (_debug) {
01263 Label L;
01264 _masm->testb(eax, Mark_Tag_Bit);
01265 _masm->jcc(Assembler::zero, L);
01266 _masm->call_C((char*)Interpreter::wrong_primitive_result, relocInfo::runtime_call_type);
01267 _masm->bind(L);
01268 }
01269 load_ebx();
01270 jump_ebx();
01271 return ep;
01272 }
01273
01274
01275 char* InterpreterGenerator::call_primitive_can_fail() {
01276 Label failed;
01277 char* ep = entry_point();
01278 advance_aligned(1 + 2*oopSize);
01279 _masm->pushl(eax);
01280 _masm->movl(eax, Address(esi, -2*oopSize));
01281 call_C(eax);
01282 _masm->testb(eax, Mark_Tag_Bit);
01283 _masm->jcc(Assembler::notZero, failed);
01284 _masm->movl(ecx, Address(esi, -oopSize));
01285 _masm->addl(esi, ecx);
01286 load_ebx();
01287 jump_ebx();
01288
01289 _masm->bind(failed);
01290 _masm->andl(eax, ~Mark_Tag_Bit);
01291 load_ebx();
01292 jump_ebx();
01293 return ep;
01294 }
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333 char* InterpreterGenerator::call_DLL(bool async) {
01334 char* ep = entry_point();
01335 Label L;
01336 advance_aligned(1 + 3*oopSize);
01337 _masm->incl(esi);
01338 _masm->pushl(eax);
01339 _masm->movl(edx, Address(esi, -1 - oopSize));
01340 _masm->testl(edx, edx);
01341 _masm->jcc(Assembler::notZero, L);
01342 call_C((char*)DLLs::lookup_and_patch_InterpretedDLL_Cache);
01343 _masm->movl(edx, eax);
01344 _masm->bind(L);
01345 _masm->movb(ebx, Address(esi, -1));
01346 _masm->movl(ecx, esp);
01347 save_esi();
01348 _masm->call(StubRoutines::call_DLL_entry(async), relocInfo::runtime_call_type);
01349 _masm->ic_info(_nlr_testpoint, 0);
01350 restore_esi();
01351 restore_ebx();
01352 _masm->movb(ebx, Address(esi, -1));
01353 _masm->leal(esp, Address(esp, ebx, Address::times_4));
01354 _masm->popl(ecx);
01355 _masm->movl(Address(ecx, pointer_offset), eax);
01356 load_ebx();
01357 _masm->movl(eax, ecx);
01358 jump_ebx();
01359 return ep;
01360 }
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370 char* Interpreter::_redo_send_entry = NULL;
01371
01372 void InterpreterGenerator::generate_redo_send_code() {
01373 assert(Interpreter::_redo_send_entry == NULL, "code generated twice");
01374 Interpreter::_redo_send_entry = _masm->pc();
01375 restore_esi();
01376 restore_ebx();
01377 load_ebx();
01378 _masm->popl(eax);
01379 jump_ebx();
01380 }
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394 void InterpreterGenerator::call_method() {
01395
01396 save_esi();
01397 _masm->call(_method_entry);
01398 _masm->ic_info(_nlr_testpoint, 0);
01399 restore_esi();
01400 }
01401
01402
01403 char* Interpreter::_last_native_called = NULL;
01404
01405 void InterpreterGenerator::call_native(Register entry) {
01406
01407 save_esi();
01408 _masm->movl(Address(int(&Interpreter::_last_native_called), relocInfo::external_word_type), entry);
01409 _masm->call(entry);
01410 _masm->ic_info(_nlr_testpoint, 0);
01411 restore_esi();
01412 restore_ebx();
01413 }
01414
01415
01416 extern "C" char* method_entry_point = NULL;
01417 extern "C" char* block_entry_point = NULL;
01418
01419 void InterpreterGenerator::generate_method_entry_code() {
01420
01421
01422
01423
01424 const int counter_offset = methodOopDesc::counters_byte_offset();
01425 const int code_offset = methodOopDesc::codes_byte_offset();
01426
01427 assert(!_method_entry.is_bound(), "code has been generated before");
01428 Label start_setup, counter_overflow, start_execution, handle_counter_overflow, is_interpreted;
01429
01430
01431
01432
01433
01434 method_entry_point = _masm->pc();
01435 _masm->bind(_method_entry);
01436 _masm->movl(edi, nil_addr());
01437
01438
01439
01440
01441
01442
01443 _masm->bind(start_setup);
01444 _masm->enter();
01445 _masm->pushl(eax);
01446 _masm->movl(edx, Address(ecx, counter_offset));
01447 _masm->leal(esi, Address(ecx, code_offset));
01448 _masm->addl(edx, 1 << methodOopDesc::_invocation_count_offset);
01449 _masm->pushl(esi);
01450 _masm->movl(Address(ecx, counter_offset), edx);
01451 load_ebx();
01452 _masm->cmpl(edx, 0xFFFF << methodOopDesc::_invocation_count_offset);
01453 Interpreter::_invocation_counter_addr = (int*)(_masm->pc() - oopSize);
01454 _masm->jcc(Assembler::aboveEqual, counter_overflow);
01455 _masm->bind(start_execution);
01456 _masm->movl(eax, edi);
01457 jump_ebx();
01458
01459
01460 _masm->bind(counter_overflow);
01461
01462 _masm->pushl(edi);
01463 _masm->set_last_Delta_frame_before_call();
01464 _masm->call(handle_counter_overflow);
01465 _masm->reset_last_Delta_frame();
01466 _masm->popl(edi);
01467
01468
01469
01470
01471
01472
01473 restore_esi();
01474 restore_ebx();
01475 load_ebx();
01476 _masm->jmp(start_execution);
01477
01478
01479
01480
01481 _masm->bind(handle_counter_overflow);
01482 _masm->pushl(ecx);
01483 _masm->pushl(eax);
01484 _masm->call((char*)Recompilation::methodOop_invocation_counter_overflow, relocInfo::runtime_call_type);
01485 _masm->addl(esp, 2*oopSize);
01486 _masm->ret(0);
01487
01488
01489
01490
01491
01492
01493
01494
01495 block_entry_point = _masm->pc();
01496 _masm->bind(_block_entry);
01497 _masm->movl(ecx, Address(eax, blockClosureOopDesc::method_or_entry_byte_offset()));
01498 _masm->reset_last_Delta_frame();
01499 _masm->test(ecx, Mem_Tag);
01500 _masm->jcc(Assembler::notZero, is_interpreted);
01501 _masm->jmp(ecx);
01502
01503 _masm->bind(is_interpreted);
01504
01505
01506 restore_ebx();
01507 _masm->movl(eax, Address(eax, blockClosureOopDesc::context_byte_offset()));
01508 _masm->movl(edi, eax);
01509
01510
01511
01512
01513
01514 _masm->jmp(start_setup);
01515 }
01516
01517
01518
01519
01520
01521 void InterpreterGenerator::generate_inline_cache_miss_handler() {
01522 assert(!_inline_cache_miss.is_bound(), "code has been generated before");
01523 _masm->bind(_inline_cache_miss);
01524
01525
01526 call_C((char*)InterpretedIC::inline_cache_miss);
01527 load_ebx();
01528 _masm->popl(eax);
01529 jump_ebx();
01530 }
01531
01532
01533
01534
01535
01536
01537 void InterpreterGenerator::generate_predicted_smi_send_failure_handler() {
01538 assert(!_smi_send_failure.is_bound(), "code has been generated before");
01539 char* ep = normal_send(Bytecodes::interpreted_send_1, true, false);
01540
01541
01542 _masm->bind(_smi_send_failure);
01543 _masm->pushl(edx);
01544 _masm->jmp(ep, relocInfo::runtime_call_type);
01545 }
01546
01547
01548 void InterpreterGenerator::check_smi_tags() {
01549
01550
01551 _masm->popl(edx);
01552 _masm->movl(ecx, eax);
01553 _masm->orl(ecx, edx);
01554 _masm->test(ecx, Mem_Tag);
01555 _masm->jcc(Assembler::notZero, _smi_send_failure);
01556
01557
01558 }
01559
01560
01561 char* InterpreterGenerator::smi_add() {
01562 Label overflow;
01563 char* ep = entry_point();
01564 check_smi_tags();
01565 _masm->addl(eax, edx);
01566 _masm->jcc(Assembler::overflow, overflow);
01567 advance_aligned(1 + 2*oopSize);
01568 load_ebx();
01569 jump_ebx();
01570
01571 _masm->bind(overflow);
01572
01573
01574 _masm->subl(eax, edx);
01575 _masm->jmp(_smi_send_failure);
01576 return ep;
01577 }
01578
01579
01580 char* InterpreterGenerator::smi_sub() {
01581 Label overflow;
01582 char* ep = entry_point();
01583 check_smi_tags();
01584 _masm->subl(edx, eax);
01585 _masm->jcc(Assembler::overflow, overflow);
01586 advance_aligned(1 + 2*oopSize);
01587 _masm->movl(eax, edx);
01588 load_ebx();
01589 jump_ebx();
01590
01591 _masm->bind(overflow);
01592
01593
01594 _masm->addl(edx, eax);
01595 _masm->jmp(_smi_send_failure);
01596 return ep;
01597 }
01598
01599
01600 char* InterpreterGenerator::smi_mul() {
01601 Label overflow;
01602 char* ep = entry_point();
01603 check_smi_tags();
01604 _masm->movl(ecx, eax);
01605 _masm->sarl(edx, Tag_Size);
01606 _masm->imull(eax, edx);
01607 _masm->jcc(Assembler::overflow, overflow);
01608 advance_aligned(1 + 2*oopSize);
01609 load_ebx();
01610 jump_ebx();
01611
01612 _masm->bind(overflow);
01613
01614
01615
01616 _masm->movl(eax, ecx);
01617 _masm->shll(edx, Tag_Size);
01618 _masm->jmp(_smi_send_failure);
01619 return ep;
01620 }
01621
01622
01623 char* InterpreterGenerator::smi_compare_op(Bytecodes::Code code) {
01624 Label is_true;
01625 char* ep = entry_point();
01626 check_smi_tags();
01627 advance_aligned(1 + 2*oopSize);
01628 load_ebx();
01629 _masm->cmpl(edx, eax);
01630 Assembler::Condition cc;
01631 switch (code) {
01632 case Bytecodes::smi_equal : cc = Assembler::equal; break;
01633 case Bytecodes::smi_not_equal : cc = Assembler::notEqual; break;
01634 case Bytecodes::smi_less : cc = Assembler::less; break;
01635 case Bytecodes::smi_less_equal : cc = Assembler::lessEqual; break;
01636 case Bytecodes::smi_greater : cc = Assembler::greater; break;
01637 case Bytecodes::smi_greater_equal : cc = Assembler::greaterEqual; break;
01638 default : ShouldNotReachHere();
01639 }
01640 _masm->jcc(cc, is_true);
01641 _masm->movl(eax, false_addr());
01642 jump_ebx();
01643
01644 _masm->bind(is_true);
01645 _masm->movl(eax, true_addr());
01646 jump_ebx();
01647 return ep;
01648 }
01649
01650
01651 char* InterpreterGenerator::smi_logical_op(Bytecodes::Code code) {
01652 char* ep = entry_point();
01653 check_smi_tags();
01654 advance_aligned(1 + 2*oopSize);
01655 load_ebx();
01656 switch (code) {
01657 case Bytecodes::smi_and: _masm->andl(eax, edx); break;
01658 case Bytecodes::smi_or : _masm->orl (eax, edx); break;
01659 case Bytecodes::smi_xor: _masm->xorl(eax, edx); break;
01660 default : ShouldNotReachHere();
01661 }
01662 jump_ebx();
01663 return ep;
01664 }
01665
01666
01667 char* InterpreterGenerator::smi_shift() {
01668
01669 assert(Int_Tag == 0, "check this code");
01670 Label shift_right;
01671
01672 char* ep = entry_point();
01673 check_smi_tags();
01674 advance_aligned(1 + 2*oopSize);
01675 load_ebx();
01676 _masm->sarl(eax, Tag_Size);
01677 _masm->movl(ecx, eax);
01678 _masm->jcc(Assembler::negative, shift_right);
01679
01680
01681 _masm->shll(edx);
01682 _masm->movl(eax, edx);
01683 jump_ebx();
01684
01685
01686 _masm->bind(shift_right);
01687 _masm->negl(ecx);
01688 _masm->sarl(edx);
01689 _masm->andl(edx, -1 << Tag_Size);
01690 _masm->movl(eax, edx);
01691 jump_ebx();
01692 return ep;
01693 }
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704 char* InterpreterGenerator::objArray_size() {
01705 char* ep = entry_point();
01706 Unimplemented();
01707 return ep;
01708 }
01709
01710
01711 char* InterpreterGenerator::objArray_at() {
01712 char* ep = entry_point();
01713 Unimplemented();
01714 return ep;
01715 }
01716
01717
01718 char* InterpreterGenerator::objArray_at_put() {
01719 char* ep = entry_point();
01720 Unimplemented();
01721 return ep;
01722 }
01723
01724
01725
01726
01727
01728
01729
01730 void InterpreterGenerator::return_tos(Bytecodes::ArgumentSpec arg_spec) {
01731 _masm->leave();
01732 switch (arg_spec) {
01733 case Bytecodes::recv_0_args: _masm->ret(0*oopSize); break;
01734 case Bytecodes::recv_1_args: _masm->ret(1*oopSize); break;
01735 case Bytecodes::recv_2_args: _masm->ret(2*oopSize); break;
01736 case Bytecodes::recv_n_args: {
01737
01738 _masm->movb(ebx, Address(esi, 1));
01739 _masm->popl(ecx);
01740 _masm->leal(esp, Address(esp, ebx, Address::times_4));
01741 _masm->jmp(ecx);
01742 break;
01743 }
01744 default: ShouldNotReachHere();
01745 }
01746 }
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756 extern "C" void suspend_on_error(InterpreterErrorConstants error_code);
01757
01758 void InterpreterGenerator::generate_error_handler_code() {
01759 assert(!_boolean_expected.is_bound(), "code has been generated before");
01760
01761 Label suspend, call_suspend;
01762
01763
01764
01765 _masm->bind(suspend);
01766 _masm->pushl(eax);
01767 call_C(call_suspend);
01768 should_not_reach_here();
01769
01770 _masm->bind(call_suspend);
01771 _masm->pushl(ecx);
01772 _masm->call((char*)suspend_on_error, relocInfo::runtime_call_type);
01773 should_not_reach_here();
01774
01775 _masm->bind(_boolean_expected);
01776 _masm->movl(ecx, boolean_expected);
01777 _masm->jmp(suspend);
01778
01779 _masm->bind(_float_expected);
01780 _masm->movl(ecx, float_expected);
01781 _masm->jmp(suspend);
01782
01783 _masm->bind(_NLR_to_dead_frame);
01784 _masm->movl(ecx, nonlocal_return_error);
01785 _masm->jmp(suspend);
01786
01787 _masm->bind(_halted);
01788 _masm->movl(ecx, halted);
01789 _masm->jmp(suspend);
01790 }
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820 extern "C" char* nlr_testpoint_entry = NULL;
01821 extern "C" contextOop nlr_home_context;
01822
01823 void InterpreterGenerator::generate_nonlocal_return_code() {
01824 assert(eax == NLR_result_reg, "NLR register use changed");
01825 assert(edi == NLR_home_reg , "NLR register use changed");
01826 assert(esi == NLR_homeId_reg, "NLR register use changed");
01827
01828 assert(!_issue_NLR.is_bound() , "code has been generated before");
01829 assert(!_nlr_testpoint.is_bound(), "code has been generated before");
01830
01831 Label zapped_context, loop, no_zapping, compiled_code_NLR;
01832
01833
01834 _masm->bind(zapped_context);
01835 _masm->popl(eax);
01836 _masm->addl(esi, 2);
01837 _masm->jmp(_NLR_to_dead_frame);
01838
01839 _masm->bind(_issue_NLR);
01840 _masm->pushl(eax);
01841 _masm->movl(edi, context_addr());
01842 if (_debug) {
01843
01844 }
01845
01846
01847
01848 _masm->bind(loop);
01849 _masm->movl(eax, edi);
01850 _masm->movl(edi, Address(edi, contextOopDesc::parent_byte_offset()));
01851 _masm->test(edi, Mem_Tag);
01852 _masm->jcc(Assembler::notZero, loop);
01853 _masm->testl(edi, edi);
01854 _masm->jcc(Assembler::zero, zapped_context);
01855 _masm->movl(Address(int(&nlr_home_context), relocInfo::external_word_type), eax);
01856
01857 _masm->movb(ebx, Address(esi, 1));
01858 _masm->popl(eax);
01859 _masm->movl(esi, ebx);
01860 _masm->notl(esi);
01861
01862
01863
01864
01865
01866
01867
01868 nlr_testpoint_entry = _masm->pc();
01869 _masm->bind(_nlr_testpoint);
01870
01871
01872
01873
01874
01875
01876
01877 _masm->movl(ecx, context_addr());
01878 _masm->test(ecx, Mem_Tag);
01879 _masm->jcc(Assembler::zero, no_zapping);
01880 _masm->movl(edx, Address(ecx, memOopDesc::klass_byte_offset()));
01881 _masm->cmpl(edx, contextKlass_addr());
01882 _masm->jcc(Assembler::notEqual, no_zapping);
01883 _masm->movl(ebx, Address(ecx, contextOopDesc::parent_byte_offset()));
01884 _masm->cmpl(ebx, ebp);
01885 _masm->jcc(Assembler::notEqual, no_zapping);
01886 _masm->movl(Address(ecx, contextOopDesc::parent_byte_offset()), 0);
01887
01888 _masm->bind(no_zapping);
01889 _masm->cmpl(edi, ebp);
01890 _masm->jcc(Assembler::notEqual, StubRoutines::continue_NLR_entry());
01891
01892
01893
01894
01895
01896 restore_ebx();
01897 _masm->leave();
01898 _masm->popl(ecx);
01899 _masm->notl(esi);
01900 _masm->leal(esp, Address(esp, esi, Address::times_4));
01901 _masm->jmp(ecx);
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912 }
01913
01914
01915 char* InterpreterGenerator::nonlocal_return_tos() {
01916 char* ep = entry_point();
01917 _masm->jmp(_issue_NLR);
01918 return ep;
01919 }
01920
01921
01922 char* InterpreterGenerator::nonlocal_return_self() {
01923 char* ep = entry_point();
01924 _masm->pushl(eax);
01925 _masm->movl(eax, self_addr());
01926 _masm->jmp(_issue_NLR);
01927 return ep;
01928 }
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950 char* InterpreterGenerator::normal_send(Bytecodes::Code code, bool allow_methodOop, bool allow_nmethod) {
01951 assert(allow_methodOop || allow_nmethod, "must allow at least one method representation");
01952
01953 Label is_smi, compare_class, is_methodOop, is_nmethod;
01954
01955 Bytecodes::ArgumentSpec arg_spec = Bytecodes::argument_spec(code);
01956 bool pop_tos = Bytecodes::pop_tos(code);
01957
01958
01959 int length = (arg_spec == Bytecodes::recv_n_args ? 2 : 1) + 2*oopSize;
01960 Address method_addr = Address(esi, -2*oopSize);
01961 Address klass_addr = Address(esi, -1*oopSize);
01962
01963 _masm->bind(is_smi);
01964 _masm->movl(edi, smiKlass_addr());
01965 _masm->jmp(compare_class);
01966
01967 char* ep = entry_point();
01968 load_recv(arg_spec);
01969 advance_aligned(length);
01970 _masm->test(eax, Mem_Tag);
01971 _masm->movl(ecx, method_addr);
01972 _masm->movl(edx, klass_addr);
01973 _masm->jcc(Assembler::zero, is_smi);
01974 _masm->movl(edi, Address(eax, memOopDesc::klass_byte_offset()));
01975
01976 _masm->bind(compare_class);
01977
01978
01979
01980
01981
01982
01983 _masm->cmpl(edx, edi);
01984 _masm->jcc(Assembler::notEqual, _inline_cache_miss);
01985
01986 if (allow_methodOop && allow_nmethod) {
01987
01988 _masm->test(ecx, Mem_Tag);
01989 _masm->jcc(Assembler::zero, is_nmethod);
01990 }
01991
01992 if (allow_methodOop) {
01993 _masm->bind(is_methodOop);
01994 call_method();
01995 if (arg_spec != Bytecodes::args_only) _masm->popl(ecx);
01996 load_ebx();
01997 if (pop_tos) _masm->popl(eax);
01998 jump_ebx();
01999 }
02000
02001 if (allow_nmethod) {
02002 _masm->bind(is_nmethod);
02003 call_native(ecx);
02004 if (arg_spec != Bytecodes::args_only) _masm->popl(ecx);
02005 load_ebx();
02006 if (pop_tos) _masm->popl(eax);
02007 jump_ebx();
02008 }
02009
02010 return ep;
02011 }
02012
02013
02014 char* InterpreterGenerator::interpreted_send(Bytecodes::Code code) {
02015 return normal_send(code, true, false);
02016 }
02017
02018
02019 char* InterpreterGenerator::compiled_send(Bytecodes::Code code) {
02020 return normal_send(code, false, true);
02021 }
02022
02023
02024 char* InterpreterGenerator::megamorphic_send(Bytecodes::Code code) {
02025
02026 if (Bytecodes::is_super_send(code)) return normal_send(code, true, true);
02027
02028 Label is_smi, probe_primary_cache, is_methodOop, is_nmethod, probe_secondary_cache;
02029 Bytecodes::ArgumentSpec arg_spec = Bytecodes::argument_spec(code);
02030
02031
02032 int length = (arg_spec == Bytecodes::recv_n_args ? 2 : 1) + 2*oopSize;
02033 bool pop_tos = Bytecodes::pop_tos(code);
02034 Address selector_addr = Address(esi, -2*oopSize);
02035 Address klass_addr = Address(esi, -1*oopSize);
02036
02037 _masm->bind(is_smi);
02038 _masm->movl(ecx, smiKlass_addr());
02039 _masm->jmp(probe_primary_cache);
02040
02041 char* ep = entry_point();
02042 load_recv(arg_spec);
02043 advance_aligned(length);
02044 _masm->test(eax, Mem_Tag);
02045 _masm->jcc(Assembler::zero, is_smi);
02046 _masm->movl(ecx, Address(eax, memOopDesc::klass_byte_offset()));
02047
02048
02049
02050
02051
02052
02053
02054 _masm->bind(probe_primary_cache);
02055 _masm->movl(edx, selector_addr);
02056
02057 _masm->movl(edi, ecx);
02058 _masm->xorl(edi, edx);
02059 _masm->andl(edi, (primary_cache_size - 1) << 4);
02060
02061 _masm->cmpl(ecx, Address(edi, lookupCache::primary_cache_address() + 0*oopSize));
02062 _masm->jcc(Assembler::notEqual, probe_secondary_cache);
02063 _masm->cmpl(edx, Address(edi, lookupCache::primary_cache_address() + 1*oopSize));
02064 _masm->jcc(Assembler::notEqual, probe_secondary_cache);
02065 _masm->movl(ecx, Address(edi, lookupCache::primary_cache_address() + 2*oopSize));
02066 _masm->test(ecx, Mem_Tag);
02067 _masm->jcc(Assembler::zero, is_nmethod);
02068
02069 _masm->bind(is_methodOop);
02070 call_method();
02071 if (arg_spec != Bytecodes::args_only) _masm->popl(ecx);
02072 load_ebx();
02073 if (pop_tos) _masm->popl(eax);
02074 jump_ebx();
02075
02076 _masm->bind(is_nmethod);
02077 call_native(ecx);
02078 if (arg_spec != Bytecodes::args_only) _masm->popl(ecx);
02079 load_ebx();
02080 if (pop_tos) _masm->popl(eax);
02081 jump_ebx();
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091 _masm->bind(probe_secondary_cache);
02092 _masm->andl(edi, (secondary_cache_size - 1) << 4);
02093
02094 _masm->cmpl(ecx, Address(edi, lookupCache::secondary_cache_address() + 0*oopSize));
02095 _masm->jcc(Assembler::notEqual, _inline_cache_miss);
02096 _masm->cmpl(edx, Address(edi, lookupCache::secondary_cache_address() + 1*oopSize));
02097 _masm->jcc(Assembler::notEqual, _inline_cache_miss);
02098 _masm->movl(ecx, Address(edi, lookupCache::secondary_cache_address() + 2*oopSize));
02099 _masm->test(ecx, Mem_Tag);
02100 _masm->jcc(Assembler::zero, is_nmethod);
02101 _masm->jmp(is_methodOop);
02102
02103 return ep;
02104 }
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119 char* InterpreterGenerator::polymorphic_send(Bytecodes::Code code) {
02120 Label loop, found, is_nmethod;
02121
02122 Bytecodes::ArgumentSpec arg_spec = Bytecodes::argument_spec(code);
02123 bool pop_tos = Bytecodes::pop_tos(code);
02124
02125
02126 int length = (arg_spec == Bytecodes::recv_n_args ? 2 : 1) + 2*oopSize;
02127 Address selector_addr = Address(esi, -2*oopSize);
02128 Address pic_addr = Address(esi, -1*oopSize);
02129
02130
02131 int length_offset = 2*oopSize - Mem_Tag;
02132 int data_offset = 3*oopSize - Mem_Tag;
02133
02134 char* ep = entry_point();
02135 load_recv(arg_spec);
02136 advance_aligned(length);
02137 _masm->movl(ebx, pic_addr);
02138 _masm->movl(ecx, Address(ebx, length_offset));
02139 _masm->sarl(ecx, Tag_Size + 1);
02140
02141
02142 _masm->movl(edx, smiKlass_addr());
02143 _masm->testl(eax, Mem_Tag);
02144 _masm->jcc(Assembler::zero, loop);
02145 _masm->movl(edx, Address(eax, memOopDesc::klass_byte_offset()));
02146
02147
02148 _masm->bind(loop);
02149
02150
02151
02152
02153
02154 _masm->cmpl(edx, Address(ebx, ecx, Address::times_8, data_offset - 1*oopSize, relocInfo::none));
02155 _masm->jcc(Assembler::equal, found);
02156 _masm->decl(ecx);
02157 _masm->jcc(Assembler::notZero, loop);
02158
02159
02160 _masm->jmp(_inline_cache_miss);
02161
02162 _masm->bind(found);
02163
02164
02165
02166
02167
02168 _masm->movl(ecx, Address(ebx, ecx, Address::times_8, data_offset - 2*oopSize, relocInfo::none));
02169 _masm->testl(ecx, Mem_Tag);
02170 _masm->jcc(Assembler::zero, is_nmethod);
02171 restore_ebx();
02172
02173
02174 call_method();
02175 if (arg_spec != Bytecodes::args_only) _masm->popl(ecx);
02176 load_ebx();
02177 if (pop_tos) _masm->popl(eax);
02178 jump_ebx();
02179
02180
02181 _masm->bind(is_nmethod);
02182 call_native(ecx);
02183 if (arg_spec != Bytecodes::args_only) _masm->popl(ecx);
02184 load_ebx();
02185 if (pop_tos) _masm->popl(eax);
02186 jump_ebx();
02187
02188 return ep;
02189 }
02190
02191
02192
02193
02194
02195 char* InterpreterGenerator::special_primitive_send_hint() {
02196 char* ep = entry_point();
02197 assert(Bytecodes::format(Bytecodes::special_primitive_send_1_hint) == Bytecodes::BB, "unexpected format");
02198 _masm->addl(esi, 2);
02199 load_ebx();
02200 jump_ebx();
02201 return ep;
02202 }
02203
02204
02205 char* InterpreterGenerator::halt() {
02206 char* ep = entry_point();
02207 _masm->incl(esi);
02208 _masm->jmp(_halted);
02209 return ep;
02210 }
02211
02212
02213
02214
02215
02216 char* InterpreterGenerator::generate_instruction(Bytecodes::Code code) {
02217 const bool pop = true;
02218 const bool returns_float = true;
02219
02220 switch (code) {
02221
02222 case Bytecodes::push_temp_0 : return push_temp(0);
02223 case Bytecodes::push_temp_1 : return push_temp(1);
02224 case Bytecodes::push_temp_2 : return push_temp(2);
02225 case Bytecodes::push_temp_3 : return push_temp(3);
02226 case Bytecodes::push_temp_4 : return push_temp(4);
02227 case Bytecodes::push_temp_5 : return push_temp(5);
02228 case Bytecodes::push_temp_n : return push_temp_n();
02229
02230 case Bytecodes::store_temp_0_pop : return store_temp(0, pop);
02231 case Bytecodes::store_temp_1_pop : return store_temp(1, pop);
02232 case Bytecodes::store_temp_2_pop : return store_temp(2, pop);
02233 case Bytecodes::store_temp_3_pop : return store_temp(3, pop);
02234 case Bytecodes::store_temp_4_pop : return store_temp(4, pop);
02235 case Bytecodes::store_temp_5_pop : return store_temp(5, pop);
02236 case Bytecodes::store_temp_n_pop : return store_temp_n(pop);
02237 case Bytecodes::store_temp_n : return store_temp_n();
02238
02239
02240 case Bytecodes::push_arg_1 : return push_arg(1);
02241 case Bytecodes::push_arg_2 : return push_arg(2);
02242 case Bytecodes::push_arg_3 : return push_arg(3);
02243 case Bytecodes::push_arg_n : return push_arg_n();
02244
02245
02246 case Bytecodes::allocate_temp_1 : return allocate_temps(1);
02247 case Bytecodes::allocate_temp_2 : return allocate_temps(2);
02248 case Bytecodes::allocate_temp_3 : return allocate_temps(3);
02249 case Bytecodes::allocate_temp_n : return allocate_temps_n();
02250
02251
02252 case Bytecodes::push_neg_n : return push_smi(true);
02253 case Bytecodes::push_succ_n : return push_smi(false);
02254 case Bytecodes::push_literal : return push_literal();
02255 case Bytecodes::push_tos : return push_tos();
02256 case Bytecodes::push_self : return push_self();
02257 case Bytecodes::push_nil : return push_const(nil_addr());
02258 case Bytecodes::push_true : return push_const(true_addr());
02259 case Bytecodes::push_false : return push_const(false_addr());
02260 case Bytecodes::only_pop : return only_pop();
02261
02262
02263 case Bytecodes::return_instVar : return return_instVar();
02264 case Bytecodes::push_instVar : return push_instVar();
02265 case Bytecodes::store_instVar_pop : return store_instVar(pop);
02266 case Bytecodes::store_instVar : return store_instVar();
02267
02268
02269 case Bytecodes::push_temp_0_context_0 : return push_context_temp(0, 0);
02270 case Bytecodes::push_temp_1_context_0 : return push_context_temp(0, 1);
02271 case Bytecodes::push_temp_2_context_0 : return push_context_temp(0, 2);
02272
02273 case Bytecodes::push_temp_0_context_1 : return push_context_temp(1, 0);
02274 case Bytecodes::push_temp_1_context_1 : return push_context_temp(1, 1);
02275 case Bytecodes::push_temp_2_context_1 : return push_context_temp(1, 2);
02276
02277
02278 case Bytecodes::set_self_via_context : return set_self_via_context();
02279
02280
02281 case Bytecodes::push_new_closure_context_0 : return push_closure((char*)allocateBlock0, true);
02282 case Bytecodes::push_new_closure_context_1 : return push_closure((char*)allocateBlock1, true);
02283 case Bytecodes::push_new_closure_context_2 : return push_closure((char*)allocateBlock2, true);
02284 case Bytecodes::push_new_closure_context_n : return push_closure((char*)allocateBlock , true);
02285
02286 case Bytecodes::push_new_closure_tos_0 : return push_closure((char*)allocateBlock0, false);
02287 case Bytecodes::push_new_closure_tos_1 : return push_closure((char*)allocateBlock1, false);
02288 case Bytecodes::push_new_closure_tos_2 : return push_closure((char*)allocateBlock2, false);
02289 case Bytecodes::push_new_closure_tos_n : return push_closure((char*)allocateBlock , false);
02290
02291
02292 case Bytecodes::install_new_context_method_0 : return install_context((char*)allocateContext0, true);
02293 case Bytecodes::install_new_context_method_1 : return install_context((char*)allocateContext1, true);
02294 case Bytecodes::install_new_context_method_2 : return install_context((char*)allocateContext2, true);
02295 case Bytecodes::install_new_context_method_n : return install_context((char*)allocateContext , true);
02296
02297 case Bytecodes::install_new_context_block_1 : return install_context((char*)allocateContext1, false);
02298 case Bytecodes::install_new_context_block_2 : return install_context((char*)allocateContext2, false);
02299 case Bytecodes::install_new_context_block_n : return install_context((char*)allocateContext , false);
02300
02301
02302 case Bytecodes::prim_call :
02303 case Bytecodes::prim_call_self : return call_primitive();
02304 case Bytecodes::prim_call_failure :
02305 case Bytecodes::prim_call_self_failure : return call_primitive_can_fail();
02306
02307 case Bytecodes::prim_call_lookup :
02308 case Bytecodes::prim_call_self_lookup :
02309 case Bytecodes::prim_call_failure_lookup :
02310 case Bytecodes::prim_call_self_failure_lookup : return lookup_primitive();
02311
02312 case Bytecodes::dll_call_sync : return call_DLL(false);
02313 case Bytecodes::dll_call_async : return call_DLL(true);
02314
02315
02316 case Bytecodes::float_allocate : return float_allocate();
02317 case Bytecodes::float_floatify_pop : return float_floatify();
02318 case Bytecodes::float_move : return float_move();
02319 case Bytecodes::float_set : return float_set();
02320 case Bytecodes::float_nullary_op : return float_op(0, returns_float);
02321 case Bytecodes::float_unary_op : return float_op(1, returns_float);
02322 case Bytecodes::float_binary_op : return float_op(2, returns_float);
02323 case Bytecodes::float_unary_op_to_oop : return float_op(1);
02324 case Bytecodes::float_binary_op_to_oop : return float_op(2);
02325
02326
02327 case Bytecodes::interpreted_send_0 :
02328 case Bytecodes::interpreted_send_1 :
02329 case Bytecodes::interpreted_send_2 :
02330 case Bytecodes::interpreted_send_n :
02331
02332 case Bytecodes::interpreted_send_0_pop :
02333 case Bytecodes::interpreted_send_1_pop :
02334 case Bytecodes::interpreted_send_2_pop :
02335 case Bytecodes::interpreted_send_n_pop :
02336
02337 case Bytecodes::interpreted_send_self :
02338 case Bytecodes::interpreted_send_self_pop :
02339
02340 case Bytecodes::interpreted_send_super :
02341 case Bytecodes::interpreted_send_super_pop : return interpreted_send(code);
02342
02343
02344 case Bytecodes::compiled_send_0 :
02345 case Bytecodes::compiled_send_1 :
02346 case Bytecodes::compiled_send_2 :
02347 case Bytecodes::compiled_send_n :
02348
02349 case Bytecodes::compiled_send_0_pop :
02350 case Bytecodes::compiled_send_1_pop :
02351 case Bytecodes::compiled_send_2_pop :
02352 case Bytecodes::compiled_send_n_pop :
02353
02354 case Bytecodes::compiled_send_self :
02355 case Bytecodes::compiled_send_self_pop :
02356
02357 case Bytecodes::compiled_send_super :
02358 case Bytecodes::compiled_send_super_pop : return compiled_send(code);
02359
02360
02361 case Bytecodes::polymorphic_send_0 :
02362 case Bytecodes::polymorphic_send_1 :
02363 case Bytecodes::polymorphic_send_2 :
02364 case Bytecodes::polymorphic_send_n :
02365
02366 case Bytecodes::polymorphic_send_0_pop :
02367 case Bytecodes::polymorphic_send_1_pop :
02368 case Bytecodes::polymorphic_send_2_pop :
02369 case Bytecodes::polymorphic_send_n_pop :
02370
02371 case Bytecodes::polymorphic_send_self :
02372 case Bytecodes::polymorphic_send_self_pop :
02373
02374 case Bytecodes::polymorphic_send_super :
02375 case Bytecodes::polymorphic_send_super_pop : return polymorphic_send(code);
02376
02377
02378 case Bytecodes::megamorphic_send_0 :
02379 case Bytecodes::megamorphic_send_1 :
02380 case Bytecodes::megamorphic_send_2 :
02381 case Bytecodes::megamorphic_send_n :
02382
02383 case Bytecodes::megamorphic_send_0_pop :
02384 case Bytecodes::megamorphic_send_1_pop :
02385 case Bytecodes::megamorphic_send_2_pop :
02386 case Bytecodes::megamorphic_send_n_pop :
02387
02388 case Bytecodes::megamorphic_send_self :
02389 case Bytecodes::megamorphic_send_self_pop :
02390
02391 case Bytecodes::megamorphic_send_super :
02392 case Bytecodes::megamorphic_send_super_pop : return megamorphic_send(code);
02393
02394
02395 case Bytecodes::smi_add : return smi_add();
02396 case Bytecodes::smi_sub : return smi_sub();
02397 case Bytecodes::smi_mult : return smi_mul();
02398
02399 case Bytecodes::smi_equal :
02400 case Bytecodes::smi_not_equal :
02401 case Bytecodes::smi_less :
02402 case Bytecodes::smi_less_equal :
02403 case Bytecodes::smi_greater :
02404 case Bytecodes::smi_greater_equal : return smi_compare_op(code);
02405
02406 case Bytecodes::smi_and :
02407 case Bytecodes::smi_or :
02408 case Bytecodes::smi_xor : return smi_logical_op(code);
02409 case Bytecodes::smi_shift : return smi_shift();
02410
02411
02412 case Bytecodes::non_local_return_tos_pop_n : return nonlocal_return_tos();
02413 case Bytecodes::non_local_return_self_pop_n : return nonlocal_return_self();
02414
02415
02416 case Bytecodes::push_global : return push_global();
02417 case Bytecodes::store_global_pop : return store_global(pop);
02418 case Bytecodes::store_global : return store_global();
02419
02420 case Bytecodes::push_classVar : return push_global();
02421 case Bytecodes::store_classVar_pop : return store_global(pop);
02422 case Bytecodes::store_classVar : return store_global();
02423
02424 case Bytecodes::halt : return halt();
02425
02426
02427 case Bytecodes::special_primitive_send_1_hint : return special_primitive_send_hint();
02428 default : return NULL;
02429 }
02430 ShouldNotReachHere();
02431 }
02432
02433
02434 void InterpreterGenerator::info(char* name) {
02435 if (!Disclaimer::is_product() && PrintInterpreter) {
02436 std->print("%s\n", name);
02437 _masm->code()->decode();
02438 std->cr();
02439 }
02440 }
02441
02442
02443 void InterpreterGenerator::generate_all() {
02444 Interpreter::_code_begin_addr = _masm->pc();
02445
02446
02447 Floats::init(_masm);
02448 Floats::_function_table[Floats::oopify] = float_oopify();
02449 info("Floats::oopify patch");
02450
02451
02452 generate_error_handler_code();
02453 info("error handler code");
02454
02455 generate_nonlocal_return_code();
02456 info("non-local return code");
02457
02458 generate_method_entry_code();
02459 info("method entry code");
02460
02461 generate_inline_cache_miss_handler();
02462 info("inline cache miss handler");
02463
02464 generate_predicted_smi_send_failure_handler();
02465 info("predicted smi send failure handler");
02466
02467 generate_redo_send_code();
02468 info("redo send code");
02469
02470
02471 for (int i = 0; i < Bytecodes::number_of_codes; i++) {
02472 char* start_point = _masm->pc();
02473 char* entry_point = generate_instruction((Bytecodes::Code)i);
02474 if (entry_point != NULL) {
02475
02476 Bytecodes::set_entry_point(Bytecodes::Code(i), entry_point);
02477 if (!Disclaimer::is_product() && PrintInterpreter) {
02478 #ifndef PRODUCT
02479 int length = _masm->pc() - start_point;
02480 char* name = Bytecodes::name((Bytecodes::Code)i);
02481 std->print("Bytecode 0x%02x: %s (%d bytes), entry point = 0x%x\n", i, name, length, entry_point);
02482 _masm->code()->decode();
02483 std->cr();
02484 #endif
02485 }
02486 }
02487 }
02488
02489 _masm->finalize();
02490 Interpreter::_code_end_addr = _masm->pc();
02491 }
02492
02493
02494 InterpreterGenerator::InterpreterGenerator(CodeBuffer* code, bool debug) {
02495 _masm = new MacroAssembler(code);
02496 _debug = debug;
02497 generate_all();
02498 }
02499
02500
02501
02502
02503 static const int interpreter_size = 40000;
02504 static char interpreter_code[interpreter_size];
02505
02506
02507 void interpreter_init() {
02508 const bool debug = false;
02509 if (!Disclaimer::is_product() && PrintInterpreter) {
02510 std->print("\nBytecode Interpreter\n\n");
02511 }
02512
02513 CodeBuffer* code = new CodeBuffer(&interpreter_code[0], interpreter_size);
02514 InterpreterGenerator g(code, debug);
02515
02516 if (!Disclaimer::is_product() && PrintInterpreter) {
02517 std->print("%d bytes generated for the interpreter\n", code->code_size());
02518 exit(0);
02519 }
02520
02521 Interpreter::init();
02522 }