mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 19:44:41 +02:00
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
Code in vtableStubs and templateTable moved into MacroAssembler. Reviewed-by: kvn
This commit is contained in:
parent
07321dec65
commit
26d192003f
10 changed files with 408 additions and 291 deletions
|
@ -3055,35 +3055,44 @@ void TemplateTable::invokeinterface(int byte_no) {
|
|||
// profile this call
|
||||
__ profile_virtual_call(rdx, rsi, rdi);
|
||||
|
||||
__ mov(rdi, rdx); // Save klassOop in rdi
|
||||
Label no_such_interface, no_such_method;
|
||||
|
||||
// Compute start of first itableOffsetEntry (which is at the end of the vtable)
|
||||
const int base = instanceKlass::vtable_start_offset() * wordSize;
|
||||
assert(vtableEntry::size() * wordSize == (1 << (int)Address::times_ptr), "adjust the scaling in the code below");
|
||||
__ movl(rsi, Address(rdx, instanceKlass::vtable_length_offset() * wordSize)); // Get length of vtable
|
||||
__ lea(rdx, Address(rdx, rsi, Address::times_4, base));
|
||||
if (HeapWordsPerLong > 1) {
|
||||
// Round up to align_object_offset boundary
|
||||
__ round_to(rdx, BytesPerLong);
|
||||
}
|
||||
__ lookup_interface_method(// inputs: rec. class, interface, itable index
|
||||
rdx, rax, rbx,
|
||||
// outputs: method, scan temp. reg
|
||||
rbx, rsi,
|
||||
no_such_interface);
|
||||
|
||||
Label entry, search, interface_ok;
|
||||
// rbx,: methodOop to call
|
||||
// rcx: receiver
|
||||
// Check for abstract method error
|
||||
// Note: This should be done more efficiently via a throw_abstract_method_error
|
||||
// interpreter entry point and a conditional jump to it in case of a null
|
||||
// method.
|
||||
__ testptr(rbx, rbx);
|
||||
__ jcc(Assembler::zero, no_such_method);
|
||||
|
||||
__ jmpb(entry);
|
||||
__ bind(search);
|
||||
__ addptr(rdx, itableOffsetEntry::size() * wordSize);
|
||||
// do the call
|
||||
// rcx: receiver
|
||||
// rbx,: methodOop
|
||||
__ jump_from_interpreted(rbx, rdx);
|
||||
__ should_not_reach_here();
|
||||
|
||||
__ bind(entry);
|
||||
// exception handling code follows...
|
||||
// note: must restore interpreter registers to canonical
|
||||
// state for exception handling to work correctly!
|
||||
|
||||
// Check that the entry is non-null. A null entry means that the receiver
|
||||
// class doesn't implement the interface, and wasn't the same as the
|
||||
// receiver class checked when the interface was resolved.
|
||||
__ push(rdx);
|
||||
__ movptr(rdx, Address(rdx, itableOffsetEntry::interface_offset_in_bytes()));
|
||||
__ testptr(rdx, rdx);
|
||||
__ jcc(Assembler::notZero, interface_ok);
|
||||
__ bind(no_such_method);
|
||||
// throw exception
|
||||
__ pop(rbx); // pop return address (pushed by prepare_invoke)
|
||||
__ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
|
||||
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
|
||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
|
||||
// the call_VM checks for exception, so we should never return here.
|
||||
__ should_not_reach_here();
|
||||
|
||||
__ bind(no_such_interface);
|
||||
// throw exception
|
||||
__ pop(rdx); // pop saved register first.
|
||||
__ pop(rbx); // pop return address (pushed by prepare_invoke)
|
||||
__ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
|
||||
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
|
||||
|
@ -3091,42 +3100,6 @@ void TemplateTable::invokeinterface(int byte_no) {
|
|||
InterpreterRuntime::throw_IncompatibleClassChangeError));
|
||||
// the call_VM checks for exception, so we should never return here.
|
||||
__ should_not_reach_here();
|
||||
__ bind(interface_ok);
|
||||
|
||||
__ pop(rdx);
|
||||
|
||||
__ cmpptr(rax, Address(rdx, itableOffsetEntry::interface_offset_in_bytes()));
|
||||
__ jcc(Assembler::notEqual, search);
|
||||
|
||||
__ movl(rdx, Address(rdx, itableOffsetEntry::offset_offset_in_bytes()));
|
||||
__ addptr(rdx, rdi); // Add offset to klassOop
|
||||
assert(itableMethodEntry::size() * wordSize == (1 << (int)Address::times_ptr), "adjust the scaling in the code below");
|
||||
__ movptr(rbx, Address(rdx, rbx, Address::times_ptr));
|
||||
// rbx,: methodOop to call
|
||||
// rcx: receiver
|
||||
// Check for abstract method error
|
||||
// Note: This should be done more efficiently via a throw_abstract_method_error
|
||||
// interpreter entry point and a conditional jump to it in case of a null
|
||||
// method.
|
||||
{ Label L;
|
||||
__ testptr(rbx, rbx);
|
||||
__ jcc(Assembler::notZero, L);
|
||||
// throw exception
|
||||
// note: must restore interpreter registers to canonical
|
||||
// state for exception handling to work correctly!
|
||||
__ pop(rbx); // pop return address (pushed by prepare_invoke)
|
||||
__ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
|
||||
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
|
||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
|
||||
// the call_VM checks for exception, so we should never return here.
|
||||
__ should_not_reach_here();
|
||||
__ bind(L);
|
||||
}
|
||||
|
||||
// do the call
|
||||
// rcx: receiver
|
||||
// rbx,: methodOop
|
||||
__ jump_from_interpreted(rbx, rdx);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue