hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp
changeset 2154 72a9b7284ccf
parent 2105 347008ce7984
parent 2149 3d362637b307
child 2570 ecc7862946d4
equal deleted inserted replaced
2106:ec595a5e793e 2154:72a9b7284ccf
   294 }
   294 }
   295 
   295 
   296 
   296 
   297 void TemplateTable::sipush() {
   297 void TemplateTable::sipush() {
   298   transition(vtos, itos);
   298   transition(vtos, itos);
   299   __ load_unsigned_word(rax, at_bcp(1));
   299   __ load_unsigned_short(rax, at_bcp(1));
   300   __ bswapl(rax);
   300   __ bswapl(rax);
   301   __ sarl(rax, 16);
   301   __ sarl(rax, 16);
   302 }
   302 }
   303 
   303 
   304 void TemplateTable::ldc(bool wide) {
   304 void TemplateTable::ldc(bool wide) {
   660   transition(itos, itos);
   660   transition(itos, itos);
   661   // rdx: array
   661   // rdx: array
   662   index_check(rdx, rax);  // kills rbx,
   662   index_check(rdx, rax);  // kills rbx,
   663   // rax,: index
   663   // rax,: index
   664   // can do better code for P5 - may want to improve this at some point
   664   // can do better code for P5 - may want to improve this at some point
   665   __ load_unsigned_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
   665   __ load_unsigned_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
   666   __ mov(rax, rbx);
   666   __ mov(rax, rbx);
   667 }
   667 }
   668 
   668 
   669 // iload followed by caload frequent pair
   669 // iload followed by caload frequent pair
   670 void TemplateTable::fast_icaload() {
   670 void TemplateTable::fast_icaload() {
   675   debug_only(__ verify_local_tag(frame::TagValue, rbx));
   675   debug_only(__ verify_local_tag(frame::TagValue, rbx));
   676 
   676 
   677   // rdx: array
   677   // rdx: array
   678   index_check(rdx, rax);
   678   index_check(rdx, rax);
   679   // rax,: index
   679   // rax,: index
   680   __ load_unsigned_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
   680   __ load_unsigned_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
   681   __ mov(rax, rbx);
   681   __ mov(rax, rbx);
   682 }
   682 }
   683 
   683 
   684 void TemplateTable::saload() {
   684 void TemplateTable::saload() {
   685   transition(itos, itos);
   685   transition(itos, itos);
   686   // rdx: array
   686   // rdx: array
   687   index_check(rdx, rax);  // kills rbx,
   687   index_check(rdx, rax);  // kills rbx,
   688   // rax,: index
   688   // rax,: index
   689   // can do better code for P5 - may want to improve this at some point
   689   // can do better code for P5 - may want to improve this at some point
   690   __ load_signed_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT)));
   690   __ load_signed_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT)));
   691   __ mov(rax, rbx);
   691   __ mov(rax, rbx);
   692 }
   692 }
   693 
   693 
   694 
   694 
   695 void TemplateTable::iload(int n) {
   695 void TemplateTable::iload(int n) {
  1584   LP64_ONLY(__ movslq(rdx, rdx));
  1584   LP64_ONLY(__ movslq(rdx, rdx));
  1585 
  1585 
  1586 
  1586 
  1587   // Handle all the JSR stuff here, then exit.
  1587   // Handle all the JSR stuff here, then exit.
  1588   // It's much shorter and cleaner than intermingling with the
  1588   // It's much shorter and cleaner than intermingling with the
  1589   // non-JSR normal-branch stuff occuring below.
  1589   // non-JSR normal-branch stuff occurring below.
  1590   if (is_jsr) {
  1590   if (is_jsr) {
  1591     // Pre-load the next target bytecode into EBX
  1591     // Pre-load the next target bytecode into EBX
  1592     __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1, 0));
  1592     __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1, 0));
  1593 
  1593 
  1594     // compute return address as bci in rax,
  1594     // compute return address as bci in rax,
  2308   __ bind(notObj);
  2308   __ bind(notObj);
  2309   // ctos
  2309   // ctos
  2310   __ cmpl(flags, ctos );
  2310   __ cmpl(flags, ctos );
  2311   __ jcc(Assembler::notEqual, notChar);
  2311   __ jcc(Assembler::notEqual, notChar);
  2312 
  2312 
  2313   __ load_unsigned_word(rax, lo );
  2313   __ load_unsigned_short(rax, lo );
  2314   __ push(ctos);
  2314   __ push(ctos);
  2315   if (!is_static) {
  2315   if (!is_static) {
  2316     patch_bytecode(Bytecodes::_fast_cgetfield, rcx, rbx);
  2316     patch_bytecode(Bytecodes::_fast_cgetfield, rcx, rbx);
  2317   }
  2317   }
  2318   __ jmp(Done);
  2318   __ jmp(Done);
  2320   __ bind(notChar);
  2320   __ bind(notChar);
  2321   // stos
  2321   // stos
  2322   __ cmpl(flags, stos );
  2322   __ cmpl(flags, stos );
  2323   __ jcc(Assembler::notEqual, notShort);
  2323   __ jcc(Assembler::notEqual, notShort);
  2324 
  2324 
  2325   __ load_signed_word(rax, lo );
  2325   __ load_signed_short(rax, lo );
  2326   __ push(stos);
  2326   __ push(stos);
  2327   if (!is_static) {
  2327   if (!is_static) {
  2328     patch_bytecode(Bytecodes::_fast_sgetfield, rcx, rbx);
  2328     patch_bytecode(Bytecodes::_fast_sgetfield, rcx, rbx);
  2329   }
  2329   }
  2330   __ jmp(Done);
  2330   __ jmp(Done);
  2828   const Address hi = Address(rax, rbx, Address::times_1, 1*wordSize);
  2828   const Address hi = Address(rax, rbx, Address::times_1, 1*wordSize);
  2829 
  2829 
  2830   // access field
  2830   // access field
  2831   switch (bytecode()) {
  2831   switch (bytecode()) {
  2832     case Bytecodes::_fast_bgetfield: __ movsbl(rax, lo );                 break;
  2832     case Bytecodes::_fast_bgetfield: __ movsbl(rax, lo );                 break;
  2833     case Bytecodes::_fast_sgetfield: __ load_signed_word(rax, lo );       break;
  2833     case Bytecodes::_fast_sgetfield: __ load_signed_short(rax, lo );      break;
  2834     case Bytecodes::_fast_cgetfield: __ load_unsigned_word(rax, lo );     break;
  2834     case Bytecodes::_fast_cgetfield: __ load_unsigned_short(rax, lo );    break;
  2835     case Bytecodes::_fast_igetfield: __ movl(rax, lo);                    break;
  2835     case Bytecodes::_fast_igetfield: __ movl(rax, lo);                    break;
  2836     case Bytecodes::_fast_lgetfield: __ stop("should not be rewritten");  break;
  2836     case Bytecodes::_fast_lgetfield: __ stop("should not be rewritten");  break;
  2837     case Bytecodes::_fast_fgetfield: __ fld_s(lo);                        break;
  2837     case Bytecodes::_fast_fgetfield: __ fld_s(lo);                        break;
  2838     case Bytecodes::_fast_dgetfield: __ fld_d(lo);                        break;
  2838     case Bytecodes::_fast_dgetfield: __ fld_d(lo);                        break;
  2839     case Bytecodes::_fast_agetfield: __ movptr(rax, lo); __ verify_oop(rax); break;
  2839     case Bytecodes::_fast_agetfield: __ movptr(rax, lo); __ verify_oop(rax); break;
  3053   __ verify_oop(rdx);
  3053   __ verify_oop(rdx);
  3054 
  3054 
  3055   // profile this call
  3055   // profile this call
  3056   __ profile_virtual_call(rdx, rsi, rdi);
  3056   __ profile_virtual_call(rdx, rsi, rdi);
  3057 
  3057 
  3058   __ mov(rdi, rdx); // Save klassOop in rdi
  3058   Label no_such_interface, no_such_method;
  3059 
  3059 
  3060   // Compute start of first itableOffsetEntry (which is at the end of the vtable)
  3060   __ lookup_interface_method(// inputs: rec. class, interface, itable index
  3061   const int base = instanceKlass::vtable_start_offset() * wordSize;
  3061                              rdx, rax, rbx,
  3062   assert(vtableEntry::size() * wordSize == (1 << (int)Address::times_ptr), "adjust the scaling in the code below");
  3062                              // outputs: method, scan temp. reg
  3063   __ movl(rsi, Address(rdx, instanceKlass::vtable_length_offset() * wordSize)); // Get length of vtable
  3063                              rbx, rsi,
  3064   __ lea(rdx, Address(rdx, rsi, Address::times_4, base));
  3064                              no_such_interface);
  3065   if (HeapWordsPerLong > 1) {
  3065 
  3066     // Round up to align_object_offset boundary
  3066   // rbx,: methodOop to call
  3067     __ round_to(rdx, BytesPerLong);
  3067   // rcx: receiver
  3068   }
  3068   // Check for abstract method error
  3069 
  3069   // Note: This should be done more efficiently via a throw_abstract_method_error
  3070   Label entry, search, interface_ok;
  3070   //       interpreter entry point and a conditional jump to it in case of a null
  3071 
  3071   //       method.
  3072   __ jmpb(entry);
  3072   __ testptr(rbx, rbx);
  3073   __ bind(search);
  3073   __ jcc(Assembler::zero, no_such_method);
  3074   __ addptr(rdx, itableOffsetEntry::size() * wordSize);
  3074 
  3075 
  3075   // do the call
  3076   __ bind(entry);
  3076   // rcx: receiver
  3077 
  3077   // rbx,: methodOop
  3078   // Check that the entry is non-null.  A null entry means that the receiver
  3078   __ jump_from_interpreted(rbx, rdx);
  3079   // class doesn't implement the interface, and wasn't the same as the
  3079   __ should_not_reach_here();
  3080   // receiver class checked when the interface was resolved.
  3080 
  3081   __ push(rdx);
  3081   // exception handling code follows...
  3082   __ movptr(rdx, Address(rdx, itableOffsetEntry::interface_offset_in_bytes()));
  3082   // note: must restore interpreter registers to canonical
  3083   __ testptr(rdx, rdx);
  3083   //       state for exception handling to work correctly!
  3084   __ jcc(Assembler::notZero, interface_ok);
  3084 
       
  3085   __ bind(no_such_method);
  3085   // throw exception
  3086   // throw exception
  3086   __ pop(rdx);           // pop saved register first.
  3087   __ pop(rbx);           // pop return address (pushed by prepare_invoke)
       
  3088   __ restore_bcp();      // rsi must be correct for exception handler   (was destroyed)
       
  3089   __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
       
  3090   __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
       
  3091   // the call_VM checks for exception, so we should never return here.
       
  3092   __ should_not_reach_here();
       
  3093 
       
  3094   __ bind(no_such_interface);
       
  3095   // throw exception
  3087   __ pop(rbx);           // pop return address (pushed by prepare_invoke)
  3096   __ pop(rbx);           // pop return address (pushed by prepare_invoke)
  3088   __ restore_bcp();      // rsi must be correct for exception handler   (was destroyed)
  3097   __ restore_bcp();      // rsi must be correct for exception handler   (was destroyed)
  3089   __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
  3098   __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
  3090   __ call_VM(noreg, CAST_FROM_FN_PTR(address,
  3099   __ call_VM(noreg, CAST_FROM_FN_PTR(address,
  3091                    InterpreterRuntime::throw_IncompatibleClassChangeError));
  3100                    InterpreterRuntime::throw_IncompatibleClassChangeError));
  3092   // the call_VM checks for exception, so we should never return here.
  3101   // the call_VM checks for exception, so we should never return here.
  3093   __ should_not_reach_here();
  3102   __ should_not_reach_here();
  3094   __ bind(interface_ok);
       
  3095 
       
  3096     __ pop(rdx);
       
  3097 
       
  3098     __ cmpptr(rax, Address(rdx, itableOffsetEntry::interface_offset_in_bytes()));
       
  3099     __ jcc(Assembler::notEqual, search);
       
  3100 
       
  3101     __ movl(rdx, Address(rdx, itableOffsetEntry::offset_offset_in_bytes()));
       
  3102     __ addptr(rdx, rdi); // Add offset to klassOop
       
  3103     assert(itableMethodEntry::size() * wordSize == (1 << (int)Address::times_ptr), "adjust the scaling in the code below");
       
  3104     __ movptr(rbx, Address(rdx, rbx, Address::times_ptr));
       
  3105     // rbx,: methodOop to call
       
  3106     // rcx: receiver
       
  3107     // Check for abstract method error
       
  3108     // Note: This should be done more efficiently via a throw_abstract_method_error
       
  3109     //       interpreter entry point and a conditional jump to it in case of a null
       
  3110     //       method.
       
  3111     { Label L;
       
  3112       __ testptr(rbx, rbx);
       
  3113       __ jcc(Assembler::notZero, L);
       
  3114       // throw exception
       
  3115           // note: must restore interpreter registers to canonical
       
  3116           //       state for exception handling to work correctly!
       
  3117           __ pop(rbx);           // pop return address (pushed by prepare_invoke)
       
  3118           __ restore_bcp();      // rsi must be correct for exception handler   (was destroyed)
       
  3119           __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
       
  3120       __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
       
  3121       // the call_VM checks for exception, so we should never return here.
       
  3122       __ should_not_reach_here();
       
  3123       __ bind(L);
       
  3124     }
       
  3125 
       
  3126   // do the call
       
  3127   // rcx: receiver
       
  3128   // rbx,: methodOop
       
  3129   __ jump_from_interpreted(rbx, rdx);
       
  3130 }
  3103 }
  3131 
  3104 
  3132 //----------------------------------------------------------------------------------------------------
  3105 //----------------------------------------------------------------------------------------------------
  3133 // Allocation
  3106 // Allocation
  3134 
  3107