hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp
changeset 2149 3d362637b307
parent 1217 5eb97f366a6a
child 2533 9aa50ba9a67f
equal deleted inserted replaced
2148:09c7f703773b 2149:3d362637b307
    32 
    32 
    33 #ifndef PRODUCT
    33 #ifndef PRODUCT
    34 extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index);
    34 extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index);
    35 #endif
    35 #endif
    36 
    36 
    37 // used by compiler only; may use only caller saved registers rax, rbx, rcx.
    37 // These stubs are used by the compiler only.
    38 // rdx holds first int arg, rsi, rdi, rbp are callee-save & must be preserved.
    38 // Argument registers, which must be preserved:
    39 // Leave receiver in rcx; required behavior when +OptoArgsInRegisters
    39 //   rcx - receiver (always first argument)
    40 // is modifed to put first oop in rcx.
    40 //   rdx - second argument (if any)
       
    41 // Other registers that might be usable:
       
    42 //   rax - inline cache register (is interface for itable stub)
       
    43 //   rbx - method (used when calling out to interpreter)
       
    44 // Available now, but may become callee-save at some point:
       
    45 //   rsi, rdi
       
    46 // Note that rax and rdx are also used for return values.
    41 //
    47 //
    42 VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
    48 VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
    43   const int i486_code_length = VtableStub::pd_code_size_limit(true);
    49   const int i486_code_length = VtableStub::pd_code_size_limit(true);
    44   VtableStub* s = new(i486_code_length) VtableStub(true, vtable_index);
    50   VtableStub* s = new(i486_code_length) VtableStub(true, vtable_index);
    45   ResourceMark rm;
    51   ResourceMark rm;
    92   // rcx: receiver
    98   // rcx: receiver
    93   address ame_addr = __ pc();
    99   address ame_addr = __ pc();
    94   __ jmp( Address(method, methodOopDesc::from_compiled_offset()));
   100   __ jmp( Address(method, methodOopDesc::from_compiled_offset()));
    95 
   101 
    96   masm->flush();
   102   masm->flush();
       
   103 
       
   104   if (PrintMiscellaneous && (WizardMode || Verbose)) {
       
   105     tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d",
       
   106                   vtable_index, s->entry_point(),
       
   107                   (int)(s->code_end() - s->entry_point()),
       
   108                   (int)(s->code_end() - __ pc()));
       
   109   }
       
   110   guarantee(__ pc() <= s->code_end(), "overflowed buffer");
       
   111 
    97   s->set_exception_points(npe_addr, ame_addr);
   112   s->set_exception_points(npe_addr, ame_addr);
    98   return s;
   113   return s;
    99 }
   114 }
   100 
   115 
   101 
   116 
   102 VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
   117 VtableStub* VtableStubs::create_itable_stub(int itable_index) {
   103   // Note well: pd_code_size_limit is the absolute minimum we can get away with.  If you
   118   // Note well: pd_code_size_limit is the absolute minimum we can get away with.  If you
   104   //            add code here, bump the code stub size returned by pd_code_size_limit!
   119   //            add code here, bump the code stub size returned by pd_code_size_limit!
   105   const int i486_code_length = VtableStub::pd_code_size_limit(false);
   120   const int i486_code_length = VtableStub::pd_code_size_limit(false);
   106   VtableStub* s = new(i486_code_length) VtableStub(false, vtable_index);
   121   VtableStub* s = new(i486_code_length) VtableStub(false, itable_index);
   107   ResourceMark rm;
   122   ResourceMark rm;
   108   CodeBuffer cb(s->entry_point(), i486_code_length);
   123   CodeBuffer cb(s->entry_point(), i486_code_length);
   109   MacroAssembler* masm = new MacroAssembler(&cb);
   124   MacroAssembler* masm = new MacroAssembler(&cb);
   110 
   125 
   111   // Entry arguments:
   126   // Entry arguments:
   121 
   136 
   122   assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx");
   137   assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx");
   123 
   138 
   124   // get receiver klass (also an implicit null-check)
   139   // get receiver klass (also an implicit null-check)
   125   address npe_addr = __ pc();
   140   address npe_addr = __ pc();
   126   __ movptr(rbx, Address(rcx, oopDesc::klass_offset_in_bytes()));
   141   __ movptr(rsi, Address(rcx, oopDesc::klass_offset_in_bytes()));
   127 
   142 
   128   __ mov(rsi, rbx);   // Save klass in free register
   143   // Most registers are in use; we'll use rax, rbx, rsi, rdi
   129   // Most registers are in use, so save a few
   144   // (If we need to make rsi, rdi callee-save, do a push/pop here.)
   130   __ push(rdx);
   145   const Register method = rbx;
   131   // compute itable entry offset (in words)
   146   Label throw_icce;
   132   const int base = instanceKlass::vtable_start_offset() * wordSize;
       
   133   assert(vtableEntry::size() * wordSize == 4, "adjust the scaling in the code below");
       
   134   __ movl(rdx, Address(rbx, instanceKlass::vtable_length_offset() * wordSize)); // Get length of vtable
       
   135   __ lea(rbx, Address(rbx, rdx, Address::times_ptr, base));
       
   136   if (HeapWordsPerLong > 1) {
       
   137     // Round up to align_object_offset boundary
       
   138     __ round_to(rbx, BytesPerLong);
       
   139   }
       
   140 
       
   141   Label hit, next, entry, throw_icce;
       
   142 
       
   143   __ jmpb(entry);
       
   144 
       
   145   __ bind(next);
       
   146   __ addptr(rbx, itableOffsetEntry::size() * wordSize);
       
   147 
       
   148   __ bind(entry);
       
   149 
       
   150   // If the entry is NULL then we've reached the end of the table
       
   151   // without finding the expected interface, so throw an exception
       
   152   __ movptr(rdx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
       
   153   __ testptr(rdx, rdx);
       
   154   __ jcc(Assembler::zero, throw_icce);
       
   155   __ cmpptr(rax, rdx);
       
   156   __ jcc(Assembler::notEqual, next);
       
   157 
       
   158   // We found a hit, move offset into rbx,
       
   159   __ movl(rdx, Address(rbx, itableOffsetEntry::offset_offset_in_bytes()));
       
   160 
       
   161   // Compute itableMethodEntry.
       
   162   const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes();
       
   163 
   147 
   164   // Get methodOop and entrypoint for compiler
   148   // Get methodOop and entrypoint for compiler
   165   const Register method = rbx;
   149   __ lookup_interface_method(// inputs: rec. class, interface, itable index
   166   __ movptr(method, Address(rsi, rdx, Address::times_1, method_offset));
   150                              rsi, rax, itable_index,
   167 
   151                              // outputs: method, scan temp. reg
   168   // Restore saved register, before possible trap.
   152                              method, rdi,
   169   __ pop(rdx);
   153                              throw_icce);
   170 
   154 
   171   // method (rbx): methodOop
   155   // method (rbx): methodOop
   172   // rcx: receiver
   156   // rcx: receiver
   173 
   157 
   174 #ifdef ASSERT
   158 #ifdef ASSERT
   185 
   169 
   186   address ame_addr = __ pc();
   170   address ame_addr = __ pc();
   187   __ jmp(Address(method, methodOopDesc::from_compiled_offset()));
   171   __ jmp(Address(method, methodOopDesc::from_compiled_offset()));
   188 
   172 
   189   __ bind(throw_icce);
   173   __ bind(throw_icce);
   190   // Restore saved register
       
   191   __ pop(rdx);
       
   192   __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
   174   __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
   193 
       
   194   masm->flush();
   175   masm->flush();
   195 
   176 
       
   177   if (PrintMiscellaneous && (WizardMode || Verbose)) {
       
   178     tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d",
       
   179                   itable_index, s->entry_point(),
       
   180                   (int)(s->code_end() - s->entry_point()),
       
   181                   (int)(s->code_end() - __ pc()));
       
   182   }
   196   guarantee(__ pc() <= s->code_end(), "overflowed buffer");
   183   guarantee(__ pc() <= s->code_end(), "overflowed buffer");
   197 
   184 
   198   s->set_exception_points(npe_addr, ame_addr);
   185   s->set_exception_points(npe_addr, ame_addr);
   199   return s;
   186   return s;
   200 }
   187 }
   205   if (is_vtable_stub) {
   192   if (is_vtable_stub) {
   206     // Vtable stub size
   193     // Vtable stub size
   207     return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0);
   194     return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0);
   208   } else {
   195   } else {
   209     // Itable stub size
   196     // Itable stub size
   210     return (DebugVtables ? 144 : 64) + (CountCompiledCalls ? 6 : 0);
   197     return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0);
   211   }
   198   }
   212 }
   199 }
   213 
   200 
   214 int VtableStub::pd_code_alignment() {
   201 int VtableStub::pd_code_alignment() {
   215   return wordSize;
   202   return wordSize;