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:
John R Rose 2009-03-06 21:36:50 -08:00
parent 07321dec65
commit 26d192003f
10 changed files with 408 additions and 291 deletions

View file

@ -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);
}
//----------------------------------------------------------------------------------------------------