mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8174962: Better interface invocations
Reviewed-by: jrose, coleenp, ahgross, acorn, iignatyev
This commit is contained in:
parent
65fe47bdf2
commit
fa8b858052
38 changed files with 596 additions and 340 deletions
|
@ -3081,15 +3081,15 @@ void TemplateTable::invokeinterface(int byte_no) {
|
|||
assert(byte_no == f1_byte, "use this argument");
|
||||
|
||||
const Register Rinterface = G1_scratch;
|
||||
const Register Rmethod = Lscratch;
|
||||
const Register Rret = G3_scratch;
|
||||
const Register Rindex = Lscratch;
|
||||
const Register O0_recv = O0;
|
||||
const Register O1_flags = O1;
|
||||
const Register O2_Klass = O2;
|
||||
const Register Rscratch = G4_scratch;
|
||||
assert_different_registers(Rscratch, G5_method);
|
||||
|
||||
prepare_invoke(byte_no, Rinterface, Rret, Rindex, O0_recv, O1_flags);
|
||||
prepare_invoke(byte_no, Rinterface, Rret, Rmethod, O0_recv, O1_flags);
|
||||
|
||||
// get receiver klass
|
||||
__ null_check(O0_recv, oopDesc::klass_offset_in_bytes());
|
||||
|
@ -3109,55 +3109,40 @@ void TemplateTable::invokeinterface(int byte_no) {
|
|||
|
||||
__ bind(notMethod);
|
||||
|
||||
Register Rtemp = O1_flags;
|
||||
|
||||
Label L_no_such_interface;
|
||||
|
||||
// Receiver subtype check against REFC.
|
||||
__ lookup_interface_method(// inputs: rec. class, interface, itable index
|
||||
O2_Klass, Rinterface, noreg,
|
||||
// outputs: temp reg1, temp reg2, temp reg3
|
||||
G5_method, Rscratch, Rtemp,
|
||||
L_no_such_interface,
|
||||
/*return_method=*/false);
|
||||
|
||||
__ profile_virtual_call(O2_Klass, O4);
|
||||
|
||||
//
|
||||
// find entry point to call
|
||||
//
|
||||
|
||||
// compute start of first itableOffsetEntry (which is at end of vtable)
|
||||
const int base = in_bytes(Klass::vtable_start_offset());
|
||||
Label search;
|
||||
Register Rtemp = O1_flags;
|
||||
// Get declaring interface class from method
|
||||
__ ld_ptr(Rmethod, Method::const_offset(), Rinterface);
|
||||
__ ld_ptr(Rinterface, ConstMethod::constants_offset(), Rinterface);
|
||||
__ ld_ptr(Rinterface, ConstantPool::pool_holder_offset_in_bytes(), Rinterface);
|
||||
|
||||
__ ld(O2_Klass, in_bytes(Klass::vtable_length_offset()), Rtemp);
|
||||
__ sll(Rtemp, LogBytesPerWord, Rtemp); // Rscratch *= 4;
|
||||
if (Assembler::is_simm13(base)) {
|
||||
__ add(Rtemp, base, Rtemp);
|
||||
} else {
|
||||
__ set(base, Rscratch);
|
||||
__ add(Rscratch, Rtemp, Rtemp);
|
||||
}
|
||||
__ add(O2_Klass, Rtemp, Rscratch);
|
||||
// Get itable index from method
|
||||
const Register Rindex = G5_method;
|
||||
__ ld(Rmethod, Method::itable_index_offset(), Rindex);
|
||||
__ sub(Rindex, Method::itable_index_max, Rindex);
|
||||
__ neg(Rindex);
|
||||
|
||||
__ bind(search);
|
||||
|
||||
__ ld_ptr(Rscratch, itableOffsetEntry::interface_offset_in_bytes(), Rtemp);
|
||||
{
|
||||
Label ok;
|
||||
|
||||
// Check that entry is non-null. Null entries are probably a bytecode
|
||||
// problem. If the interface isn't implemented by the receiver class,
|
||||
// the VM should throw IncompatibleClassChangeError. linkResolver checks
|
||||
// this too but that's only if the entry isn't already resolved, so we
|
||||
// need to check again.
|
||||
__ br_notnull_short( Rtemp, Assembler::pt, ok);
|
||||
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
|
||||
__ should_not_reach_here();
|
||||
__ bind(ok);
|
||||
}
|
||||
|
||||
__ cmp(Rinterface, Rtemp);
|
||||
__ brx(Assembler::notEqual, true, Assembler::pn, search);
|
||||
__ delayed()->add(Rscratch, itableOffsetEntry::size() * wordSize, Rscratch);
|
||||
|
||||
// entry found and Rscratch points to it
|
||||
__ ld(Rscratch, itableOffsetEntry::offset_offset_in_bytes(), Rscratch);
|
||||
|
||||
assert(itableMethodEntry::method_offset_in_bytes() == 0, "adjust instruction below");
|
||||
__ sll(Rindex, exact_log2(itableMethodEntry::size() * wordSize), Rindex); // Rindex *= 8;
|
||||
__ add(Rscratch, Rindex, Rscratch);
|
||||
__ ld_ptr(O2_Klass, Rscratch, G5_method);
|
||||
__ lookup_interface_method(// inputs: rec. class, interface, itable index
|
||||
O2_Klass, Rinterface, Rindex,
|
||||
// outputs: method, scan temp reg, temp reg
|
||||
G5_method, Rscratch, Rtemp,
|
||||
L_no_such_interface);
|
||||
|
||||
// Check for abstract method error.
|
||||
{
|
||||
|
@ -3174,6 +3159,10 @@ void TemplateTable::invokeinterface(int byte_no) {
|
|||
__ profile_arguments_type(G5_method, Rcall, Gargs, true);
|
||||
__ profile_called_method(G5_method, Rscratch);
|
||||
__ call_from_interpreter(Rcall, Gargs, Rret);
|
||||
|
||||
__ bind(L_no_such_interface);
|
||||
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
|
||||
__ should_not_reach_here();
|
||||
}
|
||||
|
||||
void TemplateTable::invokehandle(int byte_no) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue