提交 e464b779 编写于 作者: M mdoerr

8191907: PPC64 part of JDK-8174962: Better interface invocations

Reviewed-by: goetz
上级 2b04f898
/* /*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2014 SAP AG. All rights reserved. * Copyright 2012, 2017 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1531,11 +1531,10 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, ...@@ -1531,11 +1531,10 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
RegisterOrConstant itable_index, RegisterOrConstant itable_index,
Register method_result, Register method_result,
Register scan_temp, Register scan_temp,
Register sethi_temp, Register temp2,
Label& L_no_such_interface) { Label& L_no_such_interface,
bool return_method) {
assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
assert(itable_index.is_constant() || itable_index.as_register() == method_result,
"caller must use same register for non-constant itable index as for method");
// Compute start of first itableOffsetEntry (which is at the end of the vtable). // Compute start of first itableOffsetEntry (which is at the end of the vtable).
int vtable_base = InstanceKlass::vtable_start_offset() * wordSize; int vtable_base = InstanceKlass::vtable_start_offset() * wordSize;
...@@ -1553,15 +1552,18 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, ...@@ -1553,15 +1552,18 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
add(scan_temp, recv_klass, scan_temp); add(scan_temp, recv_klass, scan_temp);
// Adjust recv_klass by scaled itable_index, so we can free itable_index. // Adjust recv_klass by scaled itable_index, so we can free itable_index.
if (itable_index.is_register()) { if (return_method) {
Register itable_offset = itable_index.as_register(); if (itable_index.is_register()) {
sldi(itable_offset, itable_offset, logMEsize); Register itable_offset = itable_index.as_register();
if (itentry_off) addi(itable_offset, itable_offset, itentry_off); sldi(method_result, itable_offset, logMEsize);
add(recv_klass, itable_offset, recv_klass); if (itentry_off) { addi(method_result, method_result, itentry_off); }
} else { add(method_result, method_result, recv_klass);
long itable_offset = (long)itable_index.as_constant(); } else {
load_const_optimized(sethi_temp, (itable_offset<<logMEsize)+itentry_off); // static address, no relocation long itable_offset = (long)itable_index.as_constant();
add(recv_klass, sethi_temp, recv_klass); // static address, no relocation
load_const_optimized(temp2, (itable_offset << logMEsize) + itentry_off); // static address, no relocation
add(method_result, temp2, recv_klass);
}
} }
// for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
...@@ -1574,12 +1576,12 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, ...@@ -1574,12 +1576,12 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
for (int peel = 1; peel >= 0; peel--) { for (int peel = 1; peel >= 0; peel--) {
// %%%% Could load both offset and interface in one ldx, if they were // %%%% Could load both offset and interface in one ldx, if they were
// in the opposite order. This would save a load. // in the opposite order. This would save a load.
ld(method_result, itableOffsetEntry::interface_offset_in_bytes(), scan_temp); ld(temp2, itableOffsetEntry::interface_offset_in_bytes(), scan_temp);
// Check that this entry is non-null. A null entry means that // Check that this entry is non-null. A null entry means that
// the receiver class doesn't implement the interface, and wasn't the // the receiver class doesn't implement the interface, and wasn't the
// same as when the caller was compiled. // same as when the caller was compiled.
cmpd(CCR0, method_result, intf_klass); cmpd(CCR0, temp2, intf_klass);
if (peel) { if (peel) {
beq(CCR0, found_method); beq(CCR0, found_method);
...@@ -1592,7 +1594,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, ...@@ -1592,7 +1594,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
bind(search); bind(search);
cmpdi(CCR0, method_result, 0); cmpdi(CCR0, temp2, 0);
beq(CCR0, L_no_such_interface); beq(CCR0, L_no_such_interface);
addi(scan_temp, scan_temp, scan_step); addi(scan_temp, scan_temp, scan_step);
} }
...@@ -1600,9 +1602,11 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, ...@@ -1600,9 +1602,11 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
bind(found_method); bind(found_method);
// Got a hit. // Got a hit.
int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); if (return_method) {
lwz(scan_temp, ito_offset, scan_temp); int ito_offset = itableOffsetEntry::offset_offset_in_bytes();
ldx(method_result, scan_temp, recv_klass); lwz(scan_temp, ito_offset, scan_temp);
ldx(method_result, scan_temp, method_result);
}
} }
// virtual method calling // virtual method calling
......
/* /*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2014 SAP AG. All rights reserved. * Copyright 2012, 2017 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -441,7 +441,8 @@ class MacroAssembler: public Assembler { ...@@ -441,7 +441,8 @@ class MacroAssembler: public Assembler {
RegisterOrConstant itable_index, RegisterOrConstant itable_index,
Register method_result, Register method_result,
Register temp_reg, Register temp2_reg, Register temp_reg, Register temp2_reg,
Label& no_such_interface); Label& no_such_interface,
bool return_method = true);
// virtual method calling // virtual method calling
void lookup_virtual_method(Register recv_klass, void lookup_virtual_method(Register recv_klass,
......
/* /*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2017 Oracle and/or its affiliates. All rights reserved.
* Copyright 2013, 2014 SAP AG. All rights reserved. * Copyright 2013, 2017 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -3418,11 +3418,11 @@ void TemplateTable::invokestatic(int byte_no) { ...@@ -3418,11 +3418,11 @@ void TemplateTable::invokestatic(int byte_no) {
void TemplateTable::invokeinterface_object_method(Register Rrecv_klass, void TemplateTable::invokeinterface_object_method(Register Rrecv_klass,
Register Rret, Register Rret,
Register Rflags, Register Rflags,
Register Rindex, Register Rmethod,
Register Rtemp1, Register Rtemp1,
Register Rtemp2) { Register Rtemp2) {
assert_different_registers(Rindex, Rret, Rrecv_klass, Rflags, Rtemp1, Rtemp2); assert_different_registers(Rmethod, Rret, Rrecv_klass, Rflags, Rtemp1, Rtemp2);
Label LnotFinal; Label LnotFinal;
// Check for vfinal. // Check for vfinal.
...@@ -3434,14 +3434,14 @@ void TemplateTable::invokeinterface_object_method(Register Rrecv_klass, ...@@ -3434,14 +3434,14 @@ void TemplateTable::invokeinterface_object_method(Register Rrecv_klass,
// Final call case. // Final call case.
__ profile_final_call(Rtemp1, Rscratch); __ profile_final_call(Rtemp1, Rscratch);
// Argument and return type profiling. // Argument and return type profiling.
__ profile_arguments_type(Rindex, Rscratch, Rrecv_klass /* scratch */, true); __ profile_arguments_type(Rmethod, Rscratch, Rrecv_klass /* scratch */, true);
// Do the final call - the index (f2) contains the method. // Do the final call - the index (f2) contains the method.
__ call_from_interpreter(Rindex, Rret, Rscratch, Rrecv_klass /* scratch */); __ call_from_interpreter(Rmethod, Rret, Rscratch, Rrecv_klass /* scratch */);
// Non-final callc case. // Non-final callc case.
__ bind(LnotFinal); __ bind(LnotFinal);
__ profile_virtual_call(Rrecv_klass, Rtemp1, Rscratch, false); __ profile_virtual_call(Rrecv_klass, Rtemp1, Rscratch, false);
generate_vtable_call(Rrecv_klass, Rindex, Rret, Rscratch); generate_vtable_call(Rrecv_klass, Rmethod, Rret, Rscratch);
} }
void TemplateTable::invokeinterface(int byte_no) { void TemplateTable::invokeinterface(int byte_no) {
...@@ -3450,58 +3450,61 @@ void TemplateTable::invokeinterface(int byte_no) { ...@@ -3450,58 +3450,61 @@ void TemplateTable::invokeinterface(int byte_no) {
const Register Rscratch1 = R11_scratch1, const Register Rscratch1 = R11_scratch1,
Rscratch2 = R12_scratch2, Rscratch2 = R12_scratch2,
Rscratch3 = R9_ARG7, Rmethod = R6_ARG4,
Rscratch4 = R10_ARG8, Rmethod2 = R9_ARG7,
Rtable_addr = Rscratch2,
Rinterface_klass = R5_ARG3, Rinterface_klass = R5_ARG3,
Rret_type = R8_ARG6, Rret_addr = R8_ARG6,
Rret_addr = Rret_type, Rindex = R10_ARG8,
Rindex = R6_ARG4, Rreceiver = R3_ARG1,
Rreceiver = R4_ARG2, Rrecv_klass = R4_ARG2,
Rrecv_klass = Rreceiver,
Rflags = R7_ARG5; Rflags = R7_ARG5;
prepare_invoke(byte_no, Rinterface_klass, Rret_addr, Rindex, Rreceiver, Rflags, Rscratch1); prepare_invoke(byte_no, Rinterface_klass, Rret_addr, Rmethod, Rreceiver, Rflags, Rscratch1);
// Get receiver klass. // Get receiver klass.
__ null_check_throw(Rreceiver, oopDesc::klass_offset_in_bytes(), Rscratch3); __ null_check_throw(Rreceiver, oopDesc::klass_offset_in_bytes(), Rscratch2);
__ load_klass(Rrecv_klass, Rreceiver); __ load_klass(Rrecv_klass, Rreceiver);
// Check corner case object method. // Check corner case object method.
Label LobjectMethod; Label LobjectMethod, L_no_such_interface, Lthrow_ame;
__ testbitdi(CCR0, R0, Rflags, ConstantPoolCacheEntry::is_forced_virtual_shift); __ testbitdi(CCR0, R0, Rflags, ConstantPoolCacheEntry::is_forced_virtual_shift);
__ btrue(CCR0, LobjectMethod); __ btrue(CCR0, LobjectMethod);
// Fallthrough: The normal invokeinterface case. __ lookup_interface_method(Rrecv_klass, Rinterface_klass, noreg, noreg, Rscratch1, Rscratch2,
L_no_such_interface, /*return_method=*/false);
__ profile_virtual_call(Rrecv_klass, Rscratch1, Rscratch2, false); __ profile_virtual_call(Rrecv_klass, Rscratch1, Rscratch2, false);
// Find entry point to call. // Find entry point to call.
Label Lthrow_icc, Lthrow_ame;
// Result will be returned in Rindex.
__ mr(Rscratch4, Rrecv_klass);
__ mr(Rscratch3, Rindex);
__ lookup_interface_method(Rrecv_klass, Rinterface_klass, Rindex, Rindex, Rscratch1, Rscratch2, Lthrow_icc);
__ cmpdi(CCR0, Rindex, 0); // Get declaring interface class from method
__ ld(Rinterface_klass, in_bytes(Method::const_offset()), Rmethod);
__ ld(Rinterface_klass, in_bytes(ConstMethod::constants_offset()), Rinterface_klass);
__ ld(Rinterface_klass, ConstantPool::pool_holder_offset_in_bytes(), Rinterface_klass);
// Get itable index from method
__ lwa(Rindex, in_bytes(Method::itable_index_offset()), Rmethod);
__ subfic(Rindex, Rindex, Method::itable_index_max);
__ lookup_interface_method(Rrecv_klass, Rinterface_klass, Rindex, Rmethod2, Rscratch1, Rscratch2,
L_no_such_interface);
__ cmpdi(CCR0, Rmethod2, 0);
__ beq(CCR0, Lthrow_ame); __ beq(CCR0, Lthrow_ame);
// Found entry. Jump off! // Found entry. Jump off!
// Argument and return type profiling. // Argument and return type profiling.
__ profile_arguments_type(Rindex, Rscratch1, Rscratch2, true); __ profile_arguments_type(Rmethod2, Rscratch1, Rscratch2, true);
__ call_from_interpreter(Rindex, Rret_addr, Rscratch1, Rscratch2); //__ profile_called_method(Rindex, Rscratch1);
__ call_from_interpreter(Rmethod2, Rret_addr, Rscratch1, Rscratch2);
// Vtable entry was NULL => Throw abstract method error. // Vtable entry was NULL => Throw abstract method error.
__ bind(Lthrow_ame); __ bind(Lthrow_ame);
__ mr(Rrecv_klass, Rscratch4);
__ mr(Rindex, Rscratch3);
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
// Interface was not found => Throw incompatible class change error. // Interface was not found => Throw incompatible class change error.
__ bind(Lthrow_icc); __ bind(L_no_such_interface);
__ mr(Rrecv_klass, Rscratch4);
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError)); call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
DEBUG_ONLY( __ should_not_reach_here(); )
__ should_not_reach_here();
// Special case of invokeinterface called for virtual method of // Special case of invokeinterface called for virtual method of
// java.lang.Object. See ConstantPoolCacheEntry::set_method() for details: // java.lang.Object. See ConstantPoolCacheEntry::set_method() for details:
...@@ -3509,7 +3512,7 @@ void TemplateTable::invokeinterface(int byte_no) { ...@@ -3509,7 +3512,7 @@ void TemplateTable::invokeinterface(int byte_no) {
// to handle this corner case. This code isn't produced by javac, but could // to handle this corner case. This code isn't produced by javac, but could
// be produced by another compliant java compiler. // be produced by another compliant java compiler.
__ bind(LobjectMethod); __ bind(LobjectMethod);
invokeinterface_object_method(Rrecv_klass, Rret_addr, Rflags, Rindex, Rscratch1, Rscratch2); invokeinterface_object_method(Rrecv_klass, Rret_addr, Rflags, Rmethod, Rscratch1, Rscratch2);
} }
void TemplateTable::invokedynamic(int byte_no) { void TemplateTable::invokedynamic(int byte_no) {
......
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2014 SAP AG. All rights reserved. * Copyright 2012, 2017 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "code/vtableStubs.hpp" #include "code/vtableStubs.hpp"
#include "interp_masm_ppc_64.hpp" #include "interp_masm_ppc_64.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp" #include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp" #include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp" #include "runtime/sharedRuntime.hpp"
...@@ -56,17 +57,22 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { ...@@ -56,17 +57,22 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
// PPC port: use fixed size. // PPC port: use fixed size.
const int code_length = VtableStub::pd_code_size_limit(true); const int code_length = VtableStub::pd_code_size_limit(true);
VtableStub* s = new (code_length) VtableStub(true, vtable_index); VtableStub* s = new (code_length) VtableStub(true, vtable_index);
// Can be NULL if there is no free space in the code cache.
if (s == NULL) {
return NULL;
}
ResourceMark rm; ResourceMark rm;
CodeBuffer cb(s->entry_point(), code_length); CodeBuffer cb(s->entry_point(), code_length);
MacroAssembler* masm = new MacroAssembler(&cb); MacroAssembler* masm = new MacroAssembler(&cb);
address start_pc;
#ifndef PRODUCT #ifndef PRODUCT
if (CountCompiledCalls) { if (CountCompiledCalls) {
__ load_const(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr()); int offs = __ load_const_optimized(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr(), R12_scratch2, true);
__ lwz(R12_scratch2, 0, R11_scratch1); __ lwz(R12_scratch2, offs, R11_scratch1);
__ addi(R12_scratch2, R12_scratch2, 1); __ addi(R12_scratch2, R12_scratch2, 1);
__ stw(R12_scratch2, 0, R11_scratch1); __ stw(R12_scratch2, offs, R11_scratch1);
} }
#endif #endif
...@@ -116,6 +122,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { ...@@ -116,6 +122,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
__ load_with_trap_null_check(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method); __ load_with_trap_null_check(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method);
__ mtctr(R12_scratch2); __ mtctr(R12_scratch2);
__ bctr(); __ bctr();
masm->flush(); masm->flush();
guarantee(__ pc() <= s->code_end(), "overflowed buffer"); guarantee(__ pc() <= s->code_end(), "overflowed buffer");
...@@ -125,10 +132,16 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { ...@@ -125,10 +132,16 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
return s; return s;
} }
VtableStub* VtableStubs::create_itable_stub(int vtable_index) { VtableStub* VtableStubs::create_itable_stub(int itable_index) {
// PPC port: use fixed size. // PPC port: use fixed size.
const int code_length = VtableStub::pd_code_size_limit(false); const int code_length = VtableStub::pd_code_size_limit(false);
VtableStub* s = new (code_length) VtableStub(false, vtable_index); VtableStub* s = new (code_length) VtableStub(false, itable_index);
// Can be NULL if there is no free space in the code cache.
if (s == NULL) {
return NULL;
}
ResourceMark rm; ResourceMark rm;
CodeBuffer cb(s->entry_point(), code_length); CodeBuffer cb(s->entry_point(), code_length);
MacroAssembler* masm = new MacroAssembler(&cb); MacroAssembler* masm = new MacroAssembler(&cb);
...@@ -136,10 +149,10 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { ...@@ -136,10 +149,10 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
#ifndef PRODUCT #ifndef PRODUCT
if (CountCompiledCalls) { if (CountCompiledCalls) {
__ load_const(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr()); int offs = __ load_const_optimized(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr(), R12_scratch2, true);
__ lwz(R12_scratch2, 0, R11_scratch1); __ lwz(R12_scratch2, offs, R11_scratch1);
__ addi(R12_scratch2, R12_scratch2, 1); __ addi(R12_scratch2, R12_scratch2, 1);
__ stw(R12_scratch2, 0, R11_scratch1); __ stw(R12_scratch2, offs, R11_scratch1);
} }
#endif #endif
...@@ -148,61 +161,27 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { ...@@ -148,61 +161,27 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
// Entry arguments: // Entry arguments:
// R19_method: Interface // R19_method: Interface
// R3_ARG1: Receiver // R3_ARG1: Receiver
//
const Register rcvr_klass = R11_scratch1;
const Register vtable_len = R12_scratch2;
const Register itable_entry_addr = R21_tmp1;
const Register itable_interface = R22_tmp2;
// Get receiver klass. Label L_no_such_interface;
const Register rcvr_klass = R11_scratch1,
interface = R12_scratch2,
tmp1 = R21_tmp1,
tmp2 = R22_tmp2;
// We might implicit NULL fault here.
address npe_addr = __ pc(); // npe = null pointer exception address npe_addr = __ pc(); // npe = null pointer exception
__ load_klass_with_trap_null_check(rcvr_klass, R3_ARG1); __ load_klass_with_trap_null_check(rcvr_klass, R3_ARG1);
BLOCK_COMMENT("Load start of itable entries into itable_entry."); // Receiver subtype check against REFC.
__ lwz(vtable_len, InstanceKlass::vtable_length_offset() * wordSize, rcvr_klass); __ ld(interface, CompiledICHolder::holder_klass_offset(), R19_method);
__ slwi(vtable_len, vtable_len, exact_log2(vtableEntry::size() * wordSize)); __ lookup_interface_method(rcvr_klass, interface, noreg,
__ add(itable_entry_addr, vtable_len, rcvr_klass); R0, tmp1, tmp2,
L_no_such_interface, /*return_method=*/ false);
// Loop over all itable entries until desired interfaceOop(Rinterface) found.
BLOCK_COMMENT("Increment itable_entry_addr in loop.");
const int vtable_base_offset = InstanceKlass::vtable_start_offset() * wordSize;
__ addi(itable_entry_addr, itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes());
const int itable_offset_search_inc = itableOffsetEntry::size() * wordSize; // Get Method* and entrypoint for compiler
Label search; __ ld(interface, CompiledICHolder::holder_metadata_offset(), R19_method);
__ bind(search); __ lookup_interface_method(rcvr_klass, interface, itable_index,
__ ld(itable_interface, 0, itable_entry_addr); R19_method, tmp1, tmp2,
L_no_such_interface, /*return_method=*/ true);
// Handle IncompatibleClassChangeError in itable stubs.
// If the entry is NULL then we've reached the end of the table
// without finding the expected interface, so throw an exception.
BLOCK_COMMENT("Handle IncompatibleClassChangeError in itable stubs.");
Label throw_icce;
__ cmpdi(CCR1, itable_interface, 0);
__ cmpd(CCR0, itable_interface, R19_method);
__ addi(itable_entry_addr, itable_entry_addr, itable_offset_search_inc);
__ beq(CCR1, throw_icce);
__ bne(CCR0, search);
// Entry found and itable_entry_addr points to it, get offset of vtable for interface.
const Register vtable_offset = R12_scratch2;
const Register itable_method = R11_scratch1;
const int vtable_offset_offset = (itableOffsetEntry::offset_offset_in_bytes() -
itableOffsetEntry::interface_offset_in_bytes()) -
itable_offset_search_inc;
__ lwz(vtable_offset, vtable_offset_offset, itable_entry_addr);
// Compute itableMethodEntry and get method and entry point for compiler.
const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) +
itableMethodEntry::method_offset_in_bytes();
__ add(itable_method, rcvr_klass, vtable_offset);
__ ld(R19_method, method_offset, itable_method);
#ifndef PRODUCT #ifndef PRODUCT
if (DebugVtables) { if (DebugVtables) {
...@@ -224,7 +203,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { ...@@ -224,7 +203,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
__ trap_null_check(R19_method); __ trap_null_check(R19_method);
} else { } else {
__ cmpdi(CCR0, R19_method, 0); __ cmpdi(CCR0, R19_method, 0);
__ beq(CCR0, throw_icce); __ beq(CCR0, L_no_such_interface);
} }
} }
__ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method); __ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method);
...@@ -236,8 +215,8 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { ...@@ -236,8 +215,8 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
// We force resolving of the call site by jumping to the "handle // We force resolving of the call site by jumping to the "handle
// wrong method" stub, and so let the interpreter runtime do all the // wrong method" stub, and so let the interpreter runtime do all the
// dirty work. // dirty work.
__ bind(throw_icce); __ bind(L_no_such_interface);
__ load_const(R11_scratch1, SharedRuntime::get_handle_wrong_method_stub()); __ load_const_optimized(R11_scratch1, SharedRuntime::get_handle_wrong_method_stub(), R12_scratch2);
__ mtctr(R11_scratch1); __ mtctr(R11_scratch1);
__ bctr(); __ bctr();
...@@ -252,14 +231,15 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { ...@@ -252,14 +231,15 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
int VtableStub::pd_code_size_limit(bool is_vtable_stub) { int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
if (TraceJumps || DebugVtables || CountCompiledCalls || VerifyOops) { if (TraceJumps || DebugVtables || CountCompiledCalls || VerifyOops) {
return 1000; return 1000;
} else {
int decode_klass_size = MacroAssembler::instr_size_for_decode_klass_not_null();
if (is_vtable_stub) {
return 20 + decode_klass_size + 8 + 8; // Plain + cOops + Traps + safety
} else {
return 96 + decode_klass_size + 12 + 8; // Plain + cOops + Traps + safety
}
} }
int size = is_vtable_stub ? 20 + 8 : 164 + 20; // Plain + safety
if (UseCompressedClassPointers) {
size += MacroAssembler::instr_size_for_decode_klass_not_null();
}
if (!ImplicitNullChecks || !os::zero_page_read_protected()) {
size += is_vtable_stub ? 8 : 12;
}
return size;
} }
int VtableStub::pd_code_alignment() { int VtableStub::pd_code_alignment() {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册