interpreter.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996, LongView Technologies, L.L.C. $Revision: 1.107 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 
00025 # include "incls/_precompiled.incl"
00026 # include "incls/_interpreter.cpp.incl"
00027 
00028 
00029 // Interpreter stack frame
00030 //
00031 // An interpreter stack frame always provides space for at least one temporary (temp_0).
00032 // This speeds up method activation for methods with less than 2 temporaries. More
00033 // temporaries are allocated via special Bytecodes. Furthermore: Since there is always
00034 // (at least) one temporary, which in case of context extensions holds the pointer to
00035 // the heap-allocated context, non-local returns become simpler, because they can assume
00036 // at least temp_0 to be there (if there is a chance of having no temporaries and a self
00037 // send without args, the temp0 location would contain the return address of the callee
00038 // (a non-oop), if there were no temp_0 always).
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 // Interpreter boundaries
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;            // see interpreter_asm.asm
00058 extern "C" interpreter_loop_counter_limit;      // see interpreter_asm.asm
00059 
00060 
00061 // Boundaries of assembled interpreter code
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();       // see interpreter_asm.asm
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 // Loops
00098 
00099 extern "C" void loop_counter_overflow() {
00100   // This routine can go away if the interpreter is generated
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 // Runtime routines called from interpreter_asm.asm
00143 //
00144 // The following routine is for inline_cache_miss calls from
00145 // within interpreter_asm.asm. Can go away as soon as not needed
00146 // anymore (because interpreter is generated).
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 // Runtime routines called from the generated interpreter
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   // Called from float_oopify. Get the float argument by inspecting
00210   // the stack and the argument of the Floats::oopify operation.
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 // Interpreter initialization
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 // The InterpreterGenerator contains the functionality to generate
00248 // the interpreter in the system initialization phase.
00249 
00250 class InterpreterGenerator: StackObj {
00251  private:
00252   MacroAssembler*       _masm;          // used to generate code
00253   bool                  _debug;         // indicates debug mode
00254 
00255   Label         _method_entry;          // entry point to activate method execution
00256   Label         _block_entry;           // entry point to activate block execution (primitiveValue)
00257   Label         _inline_cache_miss;     // inline cache misses handling
00258   Label         _smi_send_failure;      // handles predicted smi send failures
00259   Label         _issue_NLR;             // the starting point for NLRs in interpreted code
00260   Label         _nlr_testpoint;         // the return point for NLRs in interpreted sends
00261 
00262   Label         _boolean_expected;      // boolean expected error
00263   Label         _float_expected;        // float expected error
00264   Label         _NLR_to_dead_frame;     // NLR error
00265   Label         _halted;                // halt executed
00266 
00267   // Debugging
00268   void check_ebx();
00269   void check_oop(Register reg);
00270   void should_not_reach_here();
00271   
00272   // Arguments, temporaries & instance variables
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   // Instruction sequencing
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   // Frame addresses
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   // Constant addresses
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   // C calls
00312   void call_C(Label& L);
00313   void call_C(char* entry);
00314   void call_C(Register entry);
00315   
00316   // Parameter passing/returns
00317   void load_recv(Bytecodes::ArgumentSpec arg_spec);
00318   void return_tos(Bytecodes::ArgumentSpec arg_spec);
00319 
00320   // Instructions
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   // Non-local returns
00392   char* nonlocal_return_tos();
00393   char* nonlocal_return_self();
00394 
00395   // Instruction generation
00396   char* generate_instruction(Bytecodes::Code code);
00397 
00398   // Generation helper
00399   void  info(char* name);
00400 
00401   // Generation
00402   void  generate_all();
00403 
00404  public:
00405   InterpreterGenerator(CodeBuffer* code, bool debug);
00406 };
00407 
00408 
00409 // Debugging
00410 
00411 void InterpreterGenerator::check_ebx() {
00412   // check if ebx is 000000xx
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   // check if reg contains an oop
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   // make sure the Interpreter traps if this point is ever reached
00437   _masm->hlt();
00438 }
00439 
00440 
00441 // Arguments, temporaries & instance variables
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 // Instruction sequencing
00482 
00483 void InterpreterGenerator::skip_words(int n) {
00484   _masm->addl(esi, (n+1)*oopSize);      // advance
00485   _masm->andl(esi, -oopSize);           // align
00486 }
00487 
00488 
00489 void InterpreterGenerator::advance_aligned(int n) {
00490   _masm->addl(esi, n + oopSize - 1);    // advance
00491   _masm->andl(esi, -oopSize);           // align
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);  // save tos
00521     call_C((char*)Interpreter::trace_bytecode);
00522     _masm->popl(eax);   // restore tos
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);  // save tos
00548     call_C((char*)Interpreter::trace_bytecode);
00549     _masm->popl(eax);   // restore tos
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 // C calls
00568 //
00569 // Always use an ic info so that NLRs can be handled since
00570 // an NLR may be issued via an abort to terminate a thread.
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 // Calling conventions for sends
00597 //
00598 // For general sends the receiver and the arguments are pushed on the stack in the order
00599 // in which they appear in the source code (i.e., receiver first, first argument, etc.).
00600 // For self and super sends, the receiver is *not* pushed but taken directly from the
00601 // callers stack frame, i.e. in these cases only the arguments are on the stack.
00602 //
00603 // The callee is responsible for removing the arguments from the stack, i.e., its return
00604 // instructions have to know how many arguments there are.
00605 //
00606 // load_recv is loading the receiver into eax and makes sure that the receiver
00607 // (except for self and super sends) as well as the arguments are on the stack.
00608 
00609 
00610 void InterpreterGenerator::load_recv(Bytecodes::ArgumentSpec arg_spec) {
00611   _masm->pushl(eax); // make sure receiver & all arguments are on the stack
00612   switch (arg_spec) {
00613     case Bytecodes::recv_0_args: break; // recv already in eax
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       // byte after send byte code specifies the number of arguments (0..255)
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 // Instructions
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));    // get b
00679   _masm->addl(esi, 2);                  // advance to next bytecode
00680   _masm->pushl(eax);                    // save tos
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));                                     // get association
00808   load_ebx();
00809   _masm->movl(eax, field_addr(ecx, associationOopDesc::value_offset()));        // get value via association
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));                                     // get association
00819   load_ebx();
00820   _masm->movl(field_addr(ecx, associationOopDesc::value_offset()), eax);        // store value via association
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));            // get n (n = 0 ==> 256 temps)
00853   _masm->addl(esi, 2);                          // advance to next bytecode
00854   _masm->pushl(eax);
00855   _masm->movl(eax, nil_addr());
00856   _masm->jmp(entry);
00857 
00858   return ep;
00859 }
00860 
00861 
00862 //-----------------------------------------------------------------------------------------
00863 // Context temporaries
00864 //
00865 // Note that eax must always be pushed in the beginning since it may hold the context (temp0).
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());                // get incoming context (stored in receiver)
00872   _masm->bind(loop);                            // search for home context
00873   _masm->movl(ecx, edx);                        // save current context
00874   _masm->movl(edx, Address(edx, contextOopDesc::parent_byte_offset()));
00875   _masm->test(edx, Mem_Tag);                    // check if parent is_smi
00876   _masm->jcc(Assembler::notZero, loop);         // if not, current context is not home context
00877   _masm->movl(edx, Address(ecx, contextOopDesc::temp0_byte_offset()));
00878   _masm->movl(self_addr(), edx);                // set self in activation frame
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 // Blocks
00900 //
00901 // push_closure allocates and pushes a (block) closure on tos. The closure's fields
00902 // are initialized depending on the function arguments allocation_routine and use_context.
00903 // allocation_routine is the entry point used to allocate the block. If use_context is true,
00904 // this frame's context is used for the closure initialization, otherwise tos is used instead.
00905 // Additionally, whenever a block is created, its surrounding block or method's invocation
00906 // counter is incremented.
00907 
00908 extern "C" oop allocateBlock(smiOop nofArgs);   // Note: needs last Delta frame setup!
00909 
00910 // Note: The following routines don't need the last Delta frame to be setup
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);                                                    // save tos
00919   if (allocation_routine == (char*)allocateBlock) {
00920     // no. of arguments specified by 2nd byte
00921     _masm->movb(ebx, Address(esi, 1));                                  // get no. of arguments
00922     advance_aligned(2 + oopSize);                                       // go to next instruction
00923     _masm->shll(ebx, Tag_Size);                                         // convert into smi (pushed on the stack!)
00924     save_esi();                                                         // save vital registers
00925     _masm->pushl(ebx);                                                  // pass as argument
00926     _masm->set_last_Delta_frame_before_call();                          // allocateBlock needs last Delta frame!
00927     _masm->call((char*)allocateBlock, relocInfo::runtime_call_type);    // eax := block closure(nof. args)
00928     _masm->reset_last_Delta_frame();
00929     _masm->popl(ebx);                                                   // get rid of argument
00930   } else {
00931     // no. of arguments implied by 1st byte
00932     advance_aligned(1 + oopSize);                                       // go to next instruction
00933     save_esi();                                                         // no last Delta frame setup needed => save vital registers
00934     _masm->call(allocation_routine, relocInfo::runtime_call_type);      // eax := block closure
00935   }
00936   restore_esi();                                                        // returning from C land => restore esi (ebx is restored later)
00937   _masm->movl(ecx, Address(esi, -oopSize));                             // get block methodOop
00938   if (use_context) {                                                    // if full block then
00939     _masm->movl(edx, context_addr());                                   //   get context of this activation
00940     if (_debug) {
00941       // should check if edx is really pointing to a context
00942       // (can it ever happen that temp0 is not holding a context
00943       // but push_closure is used with the use_context attribute?)
00944     }
00945   } else {                                                              // else
00946     _masm->popl(edx);                                                   //   use tos as context information
00947   }
00948   // install methodOop and context in block closure and increment
00949   // the invocation counter of the parent (= enclosing) methodOop
00950   //
00951   // eax: block closure
00952   // ecx: block methodOop
00953   // edx: context
00954   _masm->movl(ebx, Address(ecx, methodOopDesc::selector_or_method_byte_offset()));      // get parent (= running) methodOop
00955   _masm->movl(Address(eax, blockClosureOopDesc::method_or_entry_byte_offset()), ecx);   // set block method
00956   _masm->movl(ecx, Address(ebx, methodOopDesc::counters_byte_offset()));// get counter of parent methodOop
00957   _masm->movl(Address(eax, blockClosureOopDesc::context_byte_offset()), edx);           // set context
00958   _masm->addl(ecx, 1 << methodOopDesc::_invocation_count_offset);       // increment invocation counter of parent methodOop
00959   _masm->movl(edx, eax);                                                // make sure eax is not destroyed
00960   _masm->movl(Address(ebx, methodOopDesc::counters_byte_offset()), ecx);// store counter of parent methodOop
00961   restore_ebx();
00962   load_ebx();                                                           // get next instruction
00963   _masm->store_check(edx, ecx);                                         // do a store check on edx, use ecx as scratch register
00964   jump_ebx();
00965   return ep;
00966 }
00967 
00968 
00969 //-----------------------------------------------------------------------------------------
00970 // Contexts
00971 //
00972 // install_context allocates and installs a (heap) context in temp0. The context's
00973 // fields are initialized depending on the function arguments allocation_routine and
00974 // for_method. allocation_routine is the entry point used to allocate the context. If
00975 // for_method is true, the current frame pointer (ebp) will be the context's parent,
00976 // otherwise the (incoming) context will be used as parent context.
00977 
00978 // Note: The following routines don't need the last Delta frame to be setup
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);                            // save tos
00987   if (allocation_routine == (char*)allocateContext) {
00988     // no. of variables specified by 2nd byte
00989     _masm->movb(ebx, Address(esi, 1));          // get no. of variables
00990     _masm->addl(esi, 2);                        // go to next instruction
00991     _masm->shll(ebx, Tag_Size);                 // convert into smi (pushed on the stack!)
00992     save_esi();                                 // no last Delta frame setup needed => save vital registers
00993     _masm->pushl(ebx);                          // pass as argument
00994     _masm->call((char*)allocateContext, relocInfo::runtime_call_type);          // eax := context(nof. vars)
00995     _masm->popl(ebx);                           // get rid of argument
00996   } else {
00997     // no. of variables implied by 1st byte
00998     _masm->incl(esi);                           // go to next instruction
00999     save_esi();                                 // no last Delta frame setup needed => save vital registers
01000     _masm->call(allocation_routine, relocInfo::runtime_call_type);              // eax := context
01001   }
01002   restore_esi();                                // returning from C land => restore vital registers
01003   restore_ebx();
01004   if (for_method) {                             // if method context then
01005     _masm->movl(Address(eax, contextOopDesc::parent_byte_offset()), ebp);       // parent points to method frame
01006   } else {                                      // else
01007     _masm->movl(ecx, context_addr());           // get (incoming) enclosing context
01008     if (_debug) {
01009       // should check if ecx is really pointing to a context
01010       // (can it ever happen that temp0 is not holding a context
01011       // but install_context is used with the use_context attribute?)
01012     }
01013     _masm->movl(Address(eax, contextOopDesc::parent_byte_offset()), ecx);       // parent points to enclosing context
01014   }
01015   load_ebx();                                   // get next instruction
01016   _masm->movl(context_addr(), eax);             // install context
01017   _masm->store_check(eax, ecx);                 // store check on eax, use ecx as scratch register
01018   _masm->popl(eax);                             // restore tos
01019   jump_ebx();
01020   return ep;
01021 }
01022 
01023 
01024 //-----------------------------------------------------------------------------------------
01025 // Floating-point operations
01026 //
01027 // These operations work in the float section of (interpreted) activation frames.
01028 // Within that float section, floats are indexed from max_nof_floats - 1 to 0.
01029 // Operations that work on floats have as 2nd byte the float index of the result.
01030 //
01031 // If there's a float section, the first 2 'normal' temporaries are always there,
01032 // and temp1 holds a magic value which allows the GC to determine fast whether
01033 // there is untagged data on the stack or not.
01034 //
01035 //
01036 // Stack layout if there's a float section:
01037 //
01038 // eax    top of stack
01039 // esp->[ expressions   ]
01040 //        ...
01041 //      [ expressions   ] <---- start of expression stack
01042 //      [ float m-1     ] <---- last float in float section
01043 //      [ ...           ]
01044 //      [ float 0       ] <---- first float in float section
01045 //      [ temporary n-1 ] <---- last 'normal' temporary (n is a multiple of 2 and n >= 2)
01046 //        ...
01047 //      [ temporary 1   ]       always here if there's a float section (holds Floats::magic)
01048 //      [ temporary 0   ]       always here if there's a float section
01049 //        ...
01050 // ebp->[ previous ebp  ]
01051 //
01052 //
01053 // Note that (as always) the top of expression stack is hold in eax; i.e., if the
01054 // expression stack is empty and there's a float section, the lower-half of the last
01055 // float is kept in eax! This is not a problem, however one has to make sure to push
01056 // eax before every float operation in order to have a floats completely in memory
01057 // (this is not an extra burden since eax often has to be saved anyway).
01058 
01059 char* InterpreterGenerator::float_allocate() {
01060 // Allocates (additional) temps and floats in a stack frame.
01061 // Bytecode format:
01062 //
01063 // <float_allocate code> <nofTemps> <nofFloats> <floatExprStackSize>
01064 //
01065 // <nofTemps>                   no. of additional temps to allocate (in chunks of two) besides temp0 & temp1
01066 // <nofFloats>                  no. of initialized floats to allocate
01067 // <floatExprStackSize>         no. of uninitialized floats to allocate
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     // This instruction must be the first bytecode executed in a method (if there).
01074     Label L1, L2;
01075     // check stack pointer (must point to esi save location, temp0 is in eax)
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     // check eax (corresponds now to temp0, must be initialized to nil)
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);                          // advance to next bytecode
01091   _masm->pushl(eax);                            // save tos (i.e. temp0)
01092   _masm->pushl(Floats::magic);                  // initialize temp1 (indicates a float section)
01093 
01094   // allocate additional temps in multiples of 2 (to compensate for one float)
01095   _masm->movb(ebx, Address(esi, -3));           // get nofTemps
01096   _masm->testl(ebx, ebx);                       // allocate no additional temps if nofTemps = 0
01097   _masm->jcc(Assembler::zero, tDone);
01098   _masm->movl(eax, nil_addr());
01099   _masm->bind(tLoop);
01100   _masm->pushl(eax);                            // push nil
01101   _masm->pushl(eax);                            // push nil
01102   _masm->decl(ebx);
01103   _masm->jcc(Assembler::notZero, tLoop);
01104   _masm->bind(tDone);
01105   
01106   // allocate floats
01107   _masm->movb(ebx, Address(esi, -2));           // get nofFloats
01108   _masm->testl(ebx, ebx);                       // allocate no additional floats if nofFloats = 0
01109   _masm->jcc(Assembler::zero, fDone);
01110   _masm->xorl(eax, eax);                        // use 0 to initialize the stack with 0.0
01111   _masm->bind(fLoop);
01112   _masm->pushl(eax);                            // push 0.0 (allocate a double)
01113   _masm->pushl(eax);
01114   _masm->decb(ebx);
01115   _masm->jcc(Assembler::notZero, fLoop);
01116   _masm->bind(fDone);
01117 
01118   // allocate floats expression stack
01119   assert(floatSize == 8, "change the constant for shhl below");
01120   _masm->movb(ebx, Address(esi, -1));           // get floats expression stack size
01121   _masm->shll(ebx, 3);                          // multiply with floatSize
01122   _masm->subl(esp, ebx);                        // adjust esp
01123   restore_ebx();
01124 
01125   // continue with next instruction
01126   load_ebx();                                   // continue with next instruction
01127   _masm->popl(eax);                             // restore tos in 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);                          // advance to next instruction
01138   _masm->testb(eax, Mem_Tag);                   // check if smi
01139   _masm->jcc(Assembler::zero, is_smi);
01140   _masm->movl(ecx, Address(eax, memOopDesc::klass_byte_offset()));      // check if float
01141   _masm->cmpl(ecx, doubleKlass_addr());
01142   _masm->jcc(Assembler::notEqual, _float_expected);
01143 
01144   // unbox doubleOop
01145   _masm->movb(ebx, Address(esi, -1));           // get float number
01146   _masm->fld_d(Address(eax, byteOffset(doubleOopDesc::value_offset()))); // unbox float
01147   _masm->fstp_d(float_addr(ebx));               // store float
01148   load_ebx();
01149   _masm->popl(eax);                             // discard argument
01150   jump_ebx();
01151 
01152   // convert smi
01153   _masm->bind(is_smi);
01154   _masm->movb(ebx, Address(esi, -1));           // get float number
01155   _masm->leal(ecx, float_addr(ebx));
01156   _masm->sarl(eax, Tag_Size);                   // convert smi argument into int
01157   _masm->movl(Address(ecx), eax);               // store it in memory (use float target location)
01158   _masm->fild_s(Address(ecx));                  // convert it into float
01159   _masm->fstp_d(Address(ecx));                  // store float
01160   load_ebx();
01161   _masm->popl(eax);                             // discard argument
01162   jump_ebx();
01163 
01164   return ep;
01165 }
01166 
01167 
01168 char* InterpreterGenerator::float_oopify() {
01169 // Implements the Floats::oopify operation. It is implemented
01170 // here rather than in Floats because it needs to do a C call.
01171 // Instead of returning regularly, it directly continues with
01172 // the next byte code.
01173   char* ep = entry_point();
01174   // here the return address to float_op is on the stack
01175   // discard it so that C routine can be called regularly.
01176   _masm->popl(eax);                             // discard return address
01177   _masm->fpop();                                // pop ST (in order to avoid FPU stack overflows) -> get rid of argument
01178   call_C((char*)Interpreter::oopify_FloatValue);// eax := oopify_FloatValue() (gets its argument by looking at the last bytecode)
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);                            // make sure last float is completely in memory
01188   _masm->addl(esi, 3);                          // advance to next instruction
01189   _masm->xorl(ecx, ecx);                        // clear ecx
01190   _masm->movb(ebx, Address(esi, -1));           // get source float number
01191   _masm->movb(ecx, Address(esi, -2));           // get destination float number
01192   _masm->fld_d(float_addr(ebx));                // load source
01193   load_ebx();
01194   _masm->fstp_d(float_addr(ecx));               // store at destination
01195   _masm->popl(eax);                             // re-adjust esp
01196   jump_ebx();
01197   return ep;
01198 }
01199     
01200   
01201 char* InterpreterGenerator::float_set() {
01202   char* ep = entry_point();
01203   _masm->pushl(eax);                            // make sure last float is completely in memory
01204   _masm->movb(ebx, Address(esi, 1));            // get float number
01205   advance_aligned(2 + oopSize);                 // advance to next instruction
01206   _masm->movl(ecx, Address(esi, -oopSize));     // get doubleOop address
01207   _masm->fld_d(Address(ecx, byteOffset(doubleOopDesc::value_offset()))); // unbox float
01208   _masm->fstp_d(float_addr(ebx));               // store it
01209   load_ebx();
01210   _masm->popl(eax);                             // re-adjust esp
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);                            // make sure all floats are completely in memory
01220   _masm->addl(esi, 3);                          // advance to next instruction
01221   _masm->movb(ebx, Address(esi, -2));           // get float number
01222   _masm->leal(edx, float_addr(ebx));            // get float address
01223   _masm->movb(ebx, Address(esi, -1));           // get function number
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);                             // invoke operation
01227   load_ebx();                                   // get next byte code
01228   if (returns_float) {
01229     _masm->fstp_d(Address(edx));                // store result
01230     _masm->popl(eax);                           // re-adjust esp
01231   }                                             // otherwise: result in eax
01232   jump_ebx();
01233   return ep;
01234 }
01235     
01236   
01237 //-----------------------------------------------------------------------------------------
01238 // Primitive calls
01239 //
01240 // Note: In general, when calling the VM, esi should point to the next bytecode
01241 //       instruction. This is not the case when calling primitives::lookup_and_patch()
01242 //       in lookup_primitive(). However, esi (i.e. f.hp()) is adjusted in the
01243 //       lookup_and_patch routine.
01244 
01245 char* InterpreterGenerator::lookup_primitive() {
01246   char* ep = entry_point();
01247   _masm->pushl(eax);                            // push last argument
01248   call_C((char*)primitives::lookup_and_patch);  // do the lookup and patch call site appropriately
01249   load_ebx();
01250   _masm->popl(eax);                             // restore last argument
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);                            // push last argument
01260   _masm->movl(eax, Address(esi, -oopSize));     // get primitive entry point
01261   call_C(eax);                                  // eax := primitive call(...)
01262   if (_debug) {                                 // (Pascal calling conv. => args are popped by callee)
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);                            // push last argument
01280   _masm->movl(eax, Address(esi, -2*oopSize));   // get primitive entry point
01281   call_C(eax);                                  // eax := primitive call(...) (Pascal calling conv.)
01282   _masm->testb(eax, Mark_Tag_Bit);              // if not marked then
01283   _masm->jcc(Assembler::notZero, failed);
01284   _masm->movl(ecx, Address(esi, -oopSize));     // get jump offset
01285   _masm->addl(esi, ecx);                        // jump over failure block
01286   load_ebx();
01287   jump_ebx();
01288 
01289   _masm->bind(failed);
01290   _masm->andl(eax, ~Mark_Tag_Bit);              // unmark result
01291   load_ebx();                                   // and execute failure block
01292   jump_ebx();
01293   return ep;
01294 }
01295 
01296 
01297 //-----------------------------------------------------------------------------------------
01298 // DLL calls
01299 //
01300 // Byte code structure:
01301 //
01302 //      [send           ]       (1 byte)
01303 //      ....alignment....       (0..3 bytes)
01304 //      [dll_name       ]       (1 dword)
01305 //      [function_name  ]       (1 dword)
01306 //      [0/function ptr ]       (1 dword)
01307 //      [no. of Args    ]       (1 byte)
01308 //      ...               <---  esi
01309 //
01310 // The arguments of a dll call are either smis or proxys, i.e. boxed 32 bit words
01311 // hold in a proxy object. Before calling the dll function, all arguments are con-
01312 // verted into C arguments, i.e. smis are divided by 4 and boxed 32 bit words hold
01313 // in proxys are unboxed. The arguments are then pushed in reversed order to comply
01314 // with the C calling conventions. The result of the dll call is boxed again into
01315 // a proxy object which has been pushed before the arguments.
01316 //
01317 // Because there are Delta and C frames on the same stack and the innards of the
01318 // DLL call are unknown, its call is set up in an additional frame that behaves
01319 // like a C frame (and that has its code outside the interpreters code) but that
01320 // contains a frame pointer which can be used to properly set the last Delta frame.
01321 //
01322 // The call_DLL_entry routine (see StubRoutines) needs 3 arguments to be passed
01323 // in registers as follows:
01324 //
01325 // ebx: no. of dll function arguments
01326 // ecx: address of last dll function argument
01327 // edx: dll function entry point
01328 //
01329 // NLRs through DLL calls: Note that if the DLL is returning via an NLR, the
01330 // arguments don't need to be popped since the NLR is simply returning too
01331 // (as for ordinary NLRs). Thus, NLRs are just propagated as usual. 
01332 
01333 char* InterpreterGenerator::call_DLL(bool async) {
01334   char* ep = entry_point();
01335   Label L;
01336   advance_aligned(1 + 3*oopSize);               // advance to no. of arguments byte
01337   _masm->incl(esi);                             // advance to next instruction (skip no. of arguments byte)
01338   _masm->pushl(eax);                            // push last argument
01339   _masm->movl(edx, Address(esi, -1 - oopSize)); // get dll function ptr
01340   _masm->testl(edx, edx);                       // test if function has been looked up already
01341   _masm->jcc(Assembler::notZero, L);            // and continue - otherwise lookup dll function & patch
01342   call_C((char*)DLLs::lookup_and_patch_InterpretedDLL_Cache);   // eax := returns dll function ptr
01343   _masm->movl(edx, eax);                        // move dll function ptr into right register
01344   _masm->bind(L);                               // and continue
01345   _masm->movb(ebx, Address(esi, -1));           // get no. of arguments
01346   _masm->movl(ecx, esp);                        // get address of last argument
01347   save_esi();                                   // don't use call_C because no last_Delta_frame setup needed
01348   _masm->call(StubRoutines::call_DLL_entry(async), relocInfo::runtime_call_type);// eax := DLL call via a separate frame (parameter conversion)
01349   _masm->ic_info(_nlr_testpoint, 0);
01350   restore_esi();
01351   restore_ebx();
01352   _masm->movb(ebx, Address(esi, -1));           // get no. of arguments
01353   _masm->leal(esp, Address(esp, ebx, Address::times_4)); // pop arguments
01354   _masm->popl(ecx);                             // get proxy object
01355   _masm->movl(Address(ecx, pointer_offset), eax); // box result
01356   load_ebx();
01357   _masm->movl(eax, ecx);                        // return proxy
01358   jump_ebx();
01359   return ep;
01360 }
01361 
01362 
01363 //-----------------------------------------------------------------------------------------
01364 // Redo send code
01365 //
01366 // Used to restart a send (issued via call_native) that called a zombie nmethod.
01367 // The receiver (if not a self or super send) as well as the arguments are still
01368 // on the stack and esi has been reset to the send byte code.
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();                                // has been saved by call_native
01376   restore_ebx();                                // possibly destroyed
01377   load_ebx();
01378   _masm->popl(eax);                             // get last argument into eax again
01379   jump_ebx();                                   // restart send
01380 }
01381 
01382 
01383 //-----------------------------------------------------------------------------------------
01384 // Method invocation
01385 //
01386 // call_method calls a methodOop. The registers have
01387 // to be set up as follows:
01388 //
01389 // eax: receiver
01390 // ebx: 000000xx
01391 // ecx: methodOop
01392 // parameters on the stack
01393 
01394 void InterpreterGenerator::call_method() {
01395   // trace_send code should come here - fix this
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;          // debugging only - see comment in header file
01404 
01405 void InterpreterGenerator::call_native(Register entry) {
01406   // trace_send code should come here - fix this
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);                    // ordinary inline cache info
01411   restore_esi();
01412   restore_ebx();
01413 }
01414 
01415 
01416 extern "C" char* method_entry_point = NULL;             // for interpreter_asm.asm (remove if not used anymore)
01417 extern "C" char* block_entry_point  = NULL;             // for interpreter_asm.asm (remove if not used anymore)
01418 
01419 void InterpreterGenerator::generate_method_entry_code() {
01420 // This generates the code sequence called to activate methodOop execution.
01421 // It is usually called via the call_method() macro, which saves the old
01422 // instruction counter (esi) and provides the ic_info word for NLRs.
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   // eax: receiver
01431   // ebx: 000000xx
01432   // ecx: methodOop
01433   // parameters on the stack
01434   method_entry_point = _masm->pc();
01435   _masm->bind(_method_entry);
01436   _masm->movl(edi, nil_addr());
01437 
01438   // eax: receiver
01439   // ebx: 000000xx
01440   // ecx: methodOop
01441   // edi: initial value for temp0
01442   // parameters on the stack
01443   _masm->bind(start_setup);
01444   _masm->enter();                                                       // setup new stack frame
01445   _masm->pushl(eax);                                                    // install receiver
01446   _masm->movl(edx, Address(ecx, counter_offset));                       // get method invocation counter
01447   _masm->leal(esi, Address(ecx, code_offset));                          // set bytecode pointer to first instruction
01448   _masm->addl(edx, 1 << methodOopDesc::_invocation_count_offset);       // increment invocation counter (only upper word)
01449   _masm->pushl(esi);                                                    // initialize esi stack location for profiler
01450   _masm->movl(Address(ecx, counter_offset), edx);                       // store method invocation counter
01451   load_ebx();                                                           // get first byte code of method
01452   _masm->cmpl(edx, 0xFFFF << methodOopDesc::_invocation_count_offset);  // make sure cmpl uses imm32 field
01453   Interpreter::_invocation_counter_addr = (int*)(_masm->pc() - oopSize);// compute invocation counter address
01454   _masm->jcc(Assembler::aboveEqual, counter_overflow);                  // treat invocation counter overflow
01455   _masm->bind(start_execution);                                         // continuation point after overflow
01456   _masm->movl(eax, edi);                                                // initialize temp0
01457   jump_ebx();                                                           // start execution
01458 
01459   // invocation counter overflow
01460   _masm->bind(counter_overflow);
01461   // not necessary to store esi since it has been just initialized
01462   _masm->pushl(edi);                                                    // move tos on stack (temp0, always here)
01463   _masm->set_last_Delta_frame_before_call();
01464   _masm->call(handle_counter_overflow);                                 // introduce extra frame to pass arguments
01465   _masm->reset_last_Delta_frame();
01466   _masm->popl(edi);                                                     // restore edi, used to initialize eax
01467   // Should check here if recompilation created a nmethod for this
01468   // methodOop. If so, one should redo the send and thus start the
01469   // nmethod.
01470   // If an nmethod has been created, invocation_counter_overflow
01471   // returns the continuation pc, otherwise it returns NULL.
01472   // For now: simply continue with interpreted version.
01473   restore_esi();
01474   restore_ebx();
01475   load_ebx();
01476   _masm->jmp(start_execution);
01477 
01478   // handle invocation counter overflow, use extra frame to pass arguments
01479   // eax: receiver
01480   // ecx: methodOop
01481   _masm->bind(handle_counter_overflow);
01482   _masm->pushl(ecx);                                                    // pass methodOop argument
01483   _masm->pushl(eax);                                                    // pass receiver argument
01484   _masm->call((char*)Recompilation::methodOop_invocation_counter_overflow, relocInfo::runtime_call_type); // methodOop_invocation_counter_overflow(receiver, methodOop)
01485   _masm->addl(esp, 2*oopSize);                                          // discard arguments
01486   _masm->ret(0);
01487 
01488 
01489 // This generates the code sequence called to activate block execution.
01490 // It is jumped to from one of the primitiveValue primitives. eax is
01491 // expected to hold the receiver (i.e., the block closure).
01492 
01493   // eax: receiver (block closure)
01494   // primitiveValue parameters on the stack
01495   block_entry_point = _masm->pc();
01496   _masm->bind(_block_entry);
01497   _masm->movl(ecx, Address(eax, blockClosureOopDesc::method_or_entry_byte_offset()));   // get methodOop/jump table entry out of closure
01498   _masm->reset_last_Delta_frame();                                      // if called from the interpreter, the last Delta frame is setup
01499   _masm->test(ecx, Mem_Tag);                                            // if methodOop then
01500   _masm->jcc(Assembler::notZero, is_interpreted);                       //   start methodOop execution
01501   _masm->jmp(ecx);                                                      // else jump to jump table entry
01502 
01503   _masm->bind(is_interpreted);
01504   // eax: receiver (block closure)
01505   // ecx: block methodOop
01506   restore_ebx();                                                        // if value... is called from compiled code, ebx may be not zero
01507   _masm->movl(eax, Address(eax, blockClosureOopDesc::context_byte_offset()));           // get context out of closure
01508   _masm->movl(edi, eax);                                                // initial value for temp0 is (incoming) context/value
01509   // eax: context (= receiver)
01510   // ebx: 00000000
01511   // ecx: block methodOop
01512   // edi: context (= initial value for temp0)
01513   // parameters on stack
01514   _masm->jmp(start_setup);
01515 }
01516 
01517 
01518 //-----------------------------------------------------------------------------------------
01519 // Inline cache misses
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   // We need an inline cache for NLR evaluation.
01525   // This can happen because the inline cache miss may call "doesNotUnderstand:"
01526   call_C((char*)InterpretedIC::inline_cache_miss);
01527   load_ebx();
01528   _masm->popl(eax);
01529   jump_ebx();
01530 }
01531 
01532 
01533 //-----------------------------------------------------------------------------------------
01534 // smi predicted sends
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   // Note: Has to jump to normal_send entry point because the entry point is
01541   //       not necessarily in the beginning of the normal send code pattern.
01542   _masm->bind(_smi_send_failure);
01543   _masm->pushl(edx);                                    // push receiver back on tos
01544   _masm->jmp(ep, relocInfo::runtime_call_type);
01545 }
01546 
01547 
01548 void InterpreterGenerator::check_smi_tags() {
01549   // tos: receiver
01550   // eax: argument
01551   _masm->popl(edx);                                     // get receiver
01552   _masm->movl(ecx, eax);                                // copy it to ecx
01553   _masm->orl(ecx, edx);                                 // or tag bits
01554   _masm->test(ecx, Mem_Tag);                            // if one of them is set then
01555   _masm->jcc(Assembler::notZero, _smi_send_failure);    // arguments are not bot smis
01556   // edx: receiver
01557   // eax: argument
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   // eax: argument + receiver
01573   // edx: receiver
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   // eax: argument
01593   // edx: receiver - argument
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);                                // save argument for overflow case
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   // eax: argument * (receiver >> Tag_Size)
01614   // ecx: argument
01615   // edx: receiver >> Tag_Size
01616   _masm->movl(eax, ecx);                                // restore argument
01617   _masm->shll(edx, Tag_Size);                           // undo shift
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   // overflow is ignored for now (as in smi_prims.cpp)
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);                           // convert argument (shift count) into int (sets zero flag)
01677   _masm->movl(ecx, eax);                                // move shift count into CL
01678   _masm->jcc(Assembler::negative, shift_right);         // shift right or shift left?
01679 
01680   // shift left
01681   _masm->shll(edx);                                     // else receiver << (argument mod 32)
01682   _masm->movl(eax, edx);                                // set result
01683   jump_ebx();
01684   
01685   // shift right
01686   _masm->bind(shift_right);
01687   _masm->negl(ecx);
01688   _masm->sarl(edx);                                     // receiver >> (argument mod 32)
01689   _masm->andl(edx, -1 << Tag_Size);                     // clear tag bits
01690   _masm->movl(eax, edx);                                // set result
01691   jump_ebx();
01692   return ep;
01693 }
01694   
01695 
01696 //-----------------------------------------------------------------------------------------
01697 // objArray predicted sends
01698 //
01699 // Problem: Implementation requires InterpretedICIterator to be adjusted: in case of
01700 //          special predicted primitive methods, the (non-cached) receiver is not simply
01701 //          a smi but can be an object array (or something else) depending on the primitive
01702 //          that is predicted. Think about this.
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 // Returns
01727 //
01728 // _return_tos pops the arguments and returns from a method or block.
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       // no. of arguments is in the next byte
01738       _masm->movb(ebx, Address(esi, 1));                        // get no. of arguments
01739       _masm->popl(ecx);                                         // get return address
01740       _masm->leal(esp, Address(esp, ebx, Address::times_4));    // adjust esp (remove arguments)
01741       _masm->jmp(ecx);                                          // return
01742       break;
01743     }
01744     default: ShouldNotReachHere();
01745   }
01746 }
01747 
01748 
01749 //-----------------------------------------------------------------------------------------
01750 // Error handling
01751 //
01752 // Entry points for run-time errors. eax must contain the value it had
01753 // before starting to execute the instruction that issued the error,
01754 // esi must point to the next instruction.
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   // eax: top of expression stack
01763   // ecx: error code
01764   // esi: points to next instruction
01765   _masm->bind(suspend);
01766   _masm->pushl(eax);                            // save tos
01767   call_C(call_suspend);
01768   should_not_reach_here();
01769 
01770   _masm->bind(call_suspend);                    // extra stack frame to pass error code in C land
01771   _masm->pushl(ecx);                            // pass error code
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 // Non-local returns
01795 //
01796 // nonlocal_return does a non-local return starting in the current activation frame
01797 // and returning through stack frames until it reaches the method activation frame
01798 // that corresponds to the home stack frame of the (heap) context of the current
01799 // activation. The heap contexts of all method frames (that have a heap context)
01800 // encountered inbetween are zapped (incl. the context of the home stack frame).
01801 // After determining the home stack frame via a loop, the NLR sequence is issued
01802 // as in compiled code.
01803 //
01804 // Note: Non-local returns that start in an interpreted block must end in an interpreted
01805 // method; i.e. even if the NLR goes through compiled (C) frames, it will eventually end
01806 // in an interpreter frame. Furthermore, if a NLR is possible, there is always a chain of
01807 // contexts that eventually will end with the context allocated for the NLR target method
01808 // (since NLR require contexts to be there always).
01809 //
01810 //
01811 // Registers used in compiled code to do NLRs (defined in Location.hpp):
01812 //
01813 // Note: When doing NLRs in compiled code, the nlr_home_id is used to identify the home
01814 // scope in case of inlined methods. When doing NLR starting in interpreted code and
01815 // therefore ending in interpreted code, this register is used to pass the the number of
01816 // arguments to pop because this information is needed to correctly finish the NLR. In
01817 // order to be able to distinguish between compiled and interpreted NLRs, this value is
01818 // made negative (compiled NLR home ids are always >= 0).
01819 
01820 extern "C" char* nlr_testpoint_entry = NULL;    // for interpreter_asm.asm (remove if not used anymore)
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   // context already zapped
01834   _masm->bind(zapped_context);
01835   _masm->popl(eax);                             // get NLR result back
01836   _masm->addl(esi, 2);                          // adjust esi (must point to next instruction)
01837   _masm->jmp(_NLR_to_dead_frame);
01838 
01839   _masm->bind(_issue_NLR);
01840   _masm->pushl(eax);                            // make sure context (temp0) is in memory
01841   _masm->movl(edi, context_addr());             // get context
01842   if (_debug) {
01843     // should check here if edx is really a context
01844   }
01845 
01846   // find home stack frame by following the context chain
01847   // edi: current context in chain
01848   _masm->bind(loop);                            // repeat
01849   _masm->movl(eax, edi);                        //   eax := last context used
01850   _masm->movl(edi, Address(edi, contextOopDesc::parent_byte_offset()));
01851   _masm->test(edi, Mem_Tag);                    //   edi := edi.home
01852   _masm->jcc(Assembler::notZero, loop);         // until is_smi(edi)
01853   _masm->testl(edi, edi);                       // if edi = 0 then
01854   _masm->jcc(Assembler::zero, zapped_context);  //   context has been zapped
01855   _masm->movl(Address(int(&nlr_home_context), relocInfo::external_word_type), eax); 
01856                                                 // else save the context containing the home (edi points to home stack frame)
01857   _masm->movb(ebx, Address(esi, 1));            // get no. of arguments to pop
01858   _masm->popl(eax);                             // get NLR result back
01859   _masm->movl(esi, ebx);                        // keep no. of arguments in esi
01860   _masm->notl(esi);                             // make negative to distinguish from compiled NLRs
01861   
01862   // entry point for all methods to do NLR test & continuation,
01863   // first check if context zap is necessary
01864   //
01865   // eax: NLR result
01866   // edi: NLR home
01867   // esi: no. of arguments to pop (1s complement)
01868   nlr_testpoint_entry = _masm->pc();
01869   _masm->bind(_nlr_testpoint);
01870 
01871   // check if esi is indeed negative, otherwise this would be a NLR with
01872   // target in compiled code, which would be a bug - leave it in here to
01873   // find deoptimization bugs (request from Lars)
01874   //_masm->testl(esi, esi);
01875   //_masm->jcc(Assembler::positive, compiled_code_NLR);
01876 
01877   _masm->movl(ecx, context_addr());             // get potential context
01878   _masm->test(ecx, Mem_Tag);                    // if is_smi(ecx) then
01879   _masm->jcc(Assembler::zero, no_zapping);      //   can't be a context pointer
01880   _masm->movl(edx, Address(ecx, memOopDesc::klass_byte_offset()));      // else isOop: get its class
01881   _masm->cmpl(edx, contextKlass_addr());        // if class # contextKlass then
01882   _masm->jcc(Assembler::notEqual, no_zapping);  //   is not a context
01883   _masm->movl(ebx, Address(ecx, contextOopDesc::parent_byte_offset())); // else is context: get home
01884   _masm->cmpl(ebx, ebp);                        // if home # ebp then
01885   _masm->jcc(Assembler::notEqual, no_zapping);  //   is not a methoc context
01886   _masm->movl(Address(ecx, contextOopDesc::parent_byte_offset()), 0);   // else method context: zap home
01887 
01888   _masm->bind(no_zapping);
01889   _masm->cmpl(edi, ebp);
01890   _masm->jcc(Assembler::notEqual, StubRoutines::continue_NLR_entry());
01891 
01892   // home found
01893   // eax: NLR result
01894   // edi: NLR home
01895   // esi: no. of arguments to pop (1s complement)
01896   restore_ebx();                                // make sure ebx = 0
01897   _masm->leave();                               // remove stack frame
01898   _masm->popl(ecx);                             // get return address
01899   _masm->notl(esi);                             // make positive again
01900   _masm->leal(esp, Address(esp, esi, Address::times_4));        // pop arguments
01901   _masm->jmp(ecx);                              // return
01902 
01903   // error handler for compiled code NLRs - can be removed as soon
01904   // as that test has been removed. For now just use magic imm32 to
01905   // indicate this problem.
01906   //_masm->bind(compiled_code_NLR);
01907   //_masm->hlt();
01908   //_masm->testl(eax, 0x0badcafe);
01909   //_masm->testl(eax, 0x0badcafe);
01910   //_masm->testl(eax, 0x0badcafe);
01911   //_masm->testl(eax, 0x0badcafe);
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 // Inline cache structure for non-polymorphic sends
01933 //
01934 // [send byte code ]      1 byte
01935 // [no. of args    ]      1 byte, only if arg_spec == recv_n_args
01936 // alignment .......      0..3 bytes
01937 // [selector/method]      1 word        
01938 // [0/class        ]      1 word
01939 // next instr ...... <--- esi, after advance
01940 //
01941 // normal_send generates the code for normal sends that can
01942 // deal with either methodOop or nmethod entries, or both.
01943 //
01944 // Note: As of now (7/30/96) the method sweeper is running asynchronously and might modify
01945 //       (cleanup) the inline cache while a send is in progress. Thus, the inline cache might
01946 //       have changed in the meantime which may cause problems. Right now we try to minimize
01947 //       the chance for this to happen by loading the cached method as soon as possible, thereby
01948 //       reducing the time frame for the sweeper (gri).
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   // inline cache layout
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);                          // smi case (assumed to be infrequent)
01964   _masm->movl(edi, smiKlass_addr());            // load smi klass
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);                    // check if smi
01971   _masm->movl(ecx, method_addr);                // get cached method (assuming infrequent cache misses)
01972   _masm->movl(edx, klass_addr);                 // get cached klass
01973   _masm->jcc(Assembler::zero, is_smi);
01974   _masm->movl(edi, Address(eax, memOopDesc::klass_byte_offset()));      // get recv class
01975 
01976   _masm->bind(compare_class);
01977   // eax: receiver
01978   // ebx: 000000xx (load_recv may modify bl)
01979   // ecx: cached selector/methodOop/nmethod
01980   // edx: cached klass
01981   // edi: receiver klass
01982   // esi: next instruction
01983   _masm->cmpl(edx, edi);                        // compare with inline cache
01984   _masm->jcc(Assembler::notEqual, _inline_cache_miss);
01985 
01986   if (allow_methodOop && allow_nmethod) {
01987     // make case distinction at run-time
01988     _masm->test(ecx, Mem_Tag);                  // check if nmethod
01989     _masm->jcc(Assembler::zero, is_nmethod);    // nmethods (jump table entries) are 4-byte alligned
01990   }
01991 
01992   if (allow_methodOop) {
01993     _masm->bind(is_methodOop);
01994     call_method();
01995     if (arg_spec != Bytecodes::args_only) _masm->popl(ecx);// discard receiver if on stack
01996     load_ebx();
01997     if (pop_tos) _masm->popl(eax);              // discard result if not used
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);// discard receiver if on stack
02005     load_ebx();
02006     if (pop_tos) _masm->popl(eax);              // discard result if not used
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   // Handle super sends conventionally - most probably infrequent anyway
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   // inline cache layout
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);                          // smi case (assumed to be infrequent)
02038   _masm->movl(ecx, smiKlass_addr());            // load smi klass
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);                    // check if smi
02045   _masm->jcc(Assembler::zero, is_smi);          // otherwise
02046   _masm->movl(ecx, Address(eax, memOopDesc::klass_byte_offset()));      // get recv class
02047 
02048   // probe primary cache
02049   //
02050   // eax: receiver
02051   // ebx: 000000xx
02052   // ecx: receiver klass
02053   // esi: next instruction
02054   _masm->bind(probe_primary_cache);             // compute hash value
02055   _masm->movl(edx, selector_addr);              // get selector
02056   // compute hash value
02057   _masm->movl(edi, ecx);
02058   _masm->xorl(edi, edx);
02059   _masm->andl(edi, (primary_cache_size - 1) << 4);
02060   // probe cache
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);                    // check if nmethod
02067   _masm->jcc(Assembler::zero, is_nmethod);      // nmethods (jump table entries) are 4-byte aligned
02068 
02069   _masm->bind(is_methodOop);
02070   call_method();
02071   if (arg_spec != Bytecodes::args_only) _masm->popl(ecx);// discard receiver if on stack
02072   load_ebx();
02073   if (pop_tos) _masm->popl(eax);                // discard result if not used
02074   jump_ebx();
02075 
02076   _masm->bind(is_nmethod);
02077   call_native(ecx);
02078   if (arg_spec != Bytecodes::args_only) _masm->popl(ecx);// discard receiver if on stack
02079   load_ebx();
02080   if (pop_tos) _masm->popl(eax);                // discard result if not used
02081   jump_ebx();
02082 
02083   // probe secondary cache
02084   //
02085   // eax: receiver
02086   // ebx: 000000xx
02087   // ecx: receiver klass
02088   // edx: selector
02089   // edi: primary cache index
02090   // esi: next instruction
02091   _masm->bind(probe_secondary_cache);
02092   _masm->andl(edi, (secondary_cache_size - 1) << 4);
02093   // probe cache
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);                    // check if nmethod
02100   _masm->jcc(Assembler::zero, is_nmethod);      // nmethods (jump table entries) are 4-byte aligned
02101   _masm->jmp(is_methodOop);
02102 
02103   return ep;
02104 }
02105 
02106 //-----------------------------------------------------------------------------------------
02107 // Inline cache structure for polymorphic sends
02108 //
02109 // [send byte code ]      1 byte
02110 // [no. of args    ]      1 byte, only if arg_spec == recv_n_args
02111 // alignment .......      0..3 bytes
02112 // [selector       ]      1 word        
02113 // [pic            ]      1 word
02114 // next instr ...... <--- esi, after advance
02115 //
02116 // normal_send generates the code for normal sends that can
02117 // deal with either methodOop or nmethod entries, or both.
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   // inline cache layout
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   // pic layout
02131   int length_offset = 2*oopSize - Mem_Tag;      // these constants should be mapped to the objectArrayOop definition
02132   int data_offset   = 3*oopSize - Mem_Tag;      // these constants should be mapped to the objectArrayOop definition
02133 
02134   char* ep = entry_point();
02135   load_recv(arg_spec);
02136   advance_aligned(length);
02137   _masm->movl(ebx, pic_addr);                   // get pic
02138   _masm->movl(ecx, Address(ebx, length_offset));// get pic length (smi)
02139   _masm->sarl(ecx, Tag_Size + 1);               // get pic length (int)
02140   // verifyPIC here
02141 
02142   _masm->movl(edx, smiKlass_addr());            // preload smi klass
02143   _masm->testl(eax, Mem_Tag);                   // check if smi
02144   _masm->jcc(Assembler::zero, loop);            // otherwise
02145   _masm->movl(edx, Address(eax, memOopDesc::klass_byte_offset()));      // get receiver klass
02146 
02147   // search pic for appropriate entry
02148   _masm->bind(loop);
02149   // eax: receiver
02150   // ebx: pic (objArrayOop)
02151   // ecx: counter
02152   // edx: receiver class
02153   // esi: next instruction
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   // cache miss
02160   _masm->jmp(_inline_cache_miss);
02161 
02162   _masm->bind(found);
02163   // eax: receiver
02164   // ebx: pic (objArrayOop)
02165   // ecx: counter (> 0)
02166   // edx: receiver class
02167   // esi: next instruction
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   // methodOop found
02174   call_method();
02175   if (arg_spec != Bytecodes::args_only) _masm->popl(ecx);       // discard receiver if on stack
02176   load_ebx();
02177   if (pop_tos) _masm->popl(eax);                                // discard result if not used
02178   jump_ebx();
02179 
02180   // nmethod found
02181   _masm->bind(is_nmethod);
02182   call_native(ecx);
02183   if (arg_spec != Bytecodes::args_only) _masm->popl(ecx);       // discard receiver if on stack
02184   load_ebx();
02185   if (pop_tos) _masm->popl(eax);                                // discard result if not used
02186   jump_ebx();
02187 
02188   return ep;
02189 }
02190 
02191 
02192 //-----------------------------------------------------------------------------------------
02193 // Miscellaneous
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);                          // simply skip this instruction
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);                             // advance to next instruction
02208   _masm->jmp(_halted);
02209   return ep;
02210 }
02211 
02212 
02213 //-----------------------------------------------------------------------------------------
02214 // Instruction generator
02215 
02216 char* InterpreterGenerator::generate_instruction(Bytecodes::Code code) {
02217   const bool pop                = true; // for readability
02218   const bool returns_float      = true; // for readability
02219 
02220   switch (code) {
02221     // temporaries
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     // arguments
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     // space allocation
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     // literals / expressions
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     // instance variables
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     // context temporaries
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     // self/context initialization
02278     case Bytecodes::set_self_via_context                : return set_self_via_context();
02279 
02280     // block closure allocation
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     // context allocation
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     // primitive calls
02302     case Bytecodes::prim_call                           : // fall through
02303     case Bytecodes::prim_call_self                      : return call_primitive();
02304     case Bytecodes::prim_call_failure                   : // fall through
02305     case Bytecodes::prim_call_self_failure              : return call_primitive_can_fail();
02306 
02307     case Bytecodes::prim_call_lookup                    : // fall through
02308     case Bytecodes::prim_call_self_lookup               : // fall through
02309     case Bytecodes::prim_call_failure_lookup            : // fall through
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     // floating-point operations
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     // interpreted sends
02327     case Bytecodes::interpreted_send_0                  : // fall through
02328     case Bytecodes::interpreted_send_1                  : // fall through
02329     case Bytecodes::interpreted_send_2                  : // fall through
02330     case Bytecodes::interpreted_send_n                  : // fall through
02331 
02332     case Bytecodes::interpreted_send_0_pop              : // fall through
02333     case Bytecodes::interpreted_send_1_pop              : // fall through
02334     case Bytecodes::interpreted_send_2_pop              : // fall through
02335     case Bytecodes::interpreted_send_n_pop              : // fall through
02336 
02337     case Bytecodes::interpreted_send_self               : // fall through
02338     case Bytecodes::interpreted_send_self_pop           : // fall through
02339 
02340     case Bytecodes::interpreted_send_super              : // fall through
02341     case Bytecodes::interpreted_send_super_pop          : return interpreted_send(code);
02342 
02343     // compiled sends
02344     case Bytecodes::compiled_send_0                     : // fall through
02345     case Bytecodes::compiled_send_1                     : // fall through
02346     case Bytecodes::compiled_send_2                     : // fall through
02347     case Bytecodes::compiled_send_n                     : // fall through
02348 
02349     case Bytecodes::compiled_send_0_pop                 : // fall through
02350     case Bytecodes::compiled_send_1_pop                 : // fall through
02351     case Bytecodes::compiled_send_2_pop                 : // fall through
02352     case Bytecodes::compiled_send_n_pop                 : // fall through
02353 
02354     case Bytecodes::compiled_send_self                  : // fall through
02355     case Bytecodes::compiled_send_self_pop              : // fall through
02356 
02357     case Bytecodes::compiled_send_super                 : // fall through
02358     case Bytecodes::compiled_send_super_pop             : return compiled_send(code);
02359 
02360     // polymorphic sends
02361     case Bytecodes::polymorphic_send_0                  : // fall through
02362     case Bytecodes::polymorphic_send_1                  : // fall through
02363     case Bytecodes::polymorphic_send_2                  : // fall through
02364     case Bytecodes::polymorphic_send_n                  : // fall through
02365 
02366     case Bytecodes::polymorphic_send_0_pop              : // fall through
02367     case Bytecodes::polymorphic_send_1_pop              : // fall through
02368     case Bytecodes::polymorphic_send_2_pop              : // fall through
02369     case Bytecodes::polymorphic_send_n_pop              : // fall through
02370 
02371     case Bytecodes::polymorphic_send_self               : // fall through
02372     case Bytecodes::polymorphic_send_self_pop           : // fall through
02373 
02374     case Bytecodes::polymorphic_send_super              : // fall through
02375     case Bytecodes::polymorphic_send_super_pop          : return polymorphic_send(code);
02376 
02377     // megamorphic sends
02378     case Bytecodes::megamorphic_send_0                  : // fall through
02379     case Bytecodes::megamorphic_send_1                  : // fall through
02380     case Bytecodes::megamorphic_send_2                  : // fall through
02381     case Bytecodes::megamorphic_send_n                  : // fall through
02382 
02383     case Bytecodes::megamorphic_send_0_pop              : // fall through
02384     case Bytecodes::megamorphic_send_1_pop              : // fall through
02385     case Bytecodes::megamorphic_send_2_pop              : // fall through
02386     case Bytecodes::megamorphic_send_n_pop              : // fall through
02387 
02388     case Bytecodes::megamorphic_send_self               : // fall through
02389     case Bytecodes::megamorphic_send_self_pop           : // fall through
02390 
02391     case Bytecodes::megamorphic_send_super              : // fall through
02392     case Bytecodes::megamorphic_send_super_pop          : return megamorphic_send(code);
02393 
02394     // predicted smi sends
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                           : // fall through
02400     case Bytecodes::smi_not_equal                       : // fall through
02401     case Bytecodes::smi_less                            : // fall through
02402     case Bytecodes::smi_less_equal                      : // fall through
02403     case Bytecodes::smi_greater                         : // fall through
02404     case Bytecodes::smi_greater_equal                   : return smi_compare_op(code);
02405     
02406     case Bytecodes::smi_and                             : // fall through
02407     case Bytecodes::smi_or                              : // fall through
02408     case Bytecodes::smi_xor                             : return smi_logical_op(code);
02409     case Bytecodes::smi_shift                           : return smi_shift();
02410 
02411     // returns
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     // globals
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();         // same as for globals
02421     case Bytecodes::store_classVar_pop                  : return store_global(pop);     // same as for globals
02422     case Bytecodes::store_classVar                      : return store_global();        // same as for globals
02423 
02424     case Bytecodes::halt                                : return halt();
02425 
02426     // miscellaneous
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   // generate code for Floats
02447   Floats::init(_masm);
02448   Floats::_function_table[Floats::oopify] = float_oopify();     // patch - no code generated in Floats for oopify
02449   info("Floats::oopify patch");
02450 
02451   // generate helper routines/code fragments
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   // generate individual instructions
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       // bytecode implemented
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 // Interpreter initialization
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; // change this to switch between debug/optimized version
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 }

Generated on Mon Oct 9 13:37:12 2006 for Strongtalk VM by  doxygen 1.4.7