# HG changeset patch # User aph # Date 1516381076 0 # Node ID 7c03f19d38a75cc27126e08d16b3356cff8d9c3c # Parent 67abfee27e6966cde1ce3babc4f2072c37a2d227 8195685: AArch64: AArch64 cannot build with JDK-8174962 Reviewed-by: adinn, njian diff -r 67abfee27e69 -r 7c03f19d38a7 src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Mon Jan 22 12:00:41 2018 +0800 +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Fri Jan 19 16:57:56 2018 +0000 @@ -963,8 +963,12 @@ RegisterOrConstant itable_index, Register method_result, Register scan_temp, - Label& L_no_such_interface) { - assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); + Label& L_no_such_interface, + bool return_method) { + assert_different_registers(recv_klass, intf_klass, scan_temp); + assert_different_registers(method_result, intf_klass, scan_temp); + assert(recv_klass != method_result || !return_method, + "recv_klass can be destroyed when method isn't needed"); assert(itable_index.is_constant() || itable_index.as_register() == method_result, "caller must use same register for non-constant itable index as for method"); @@ -982,12 +986,14 @@ lea(scan_temp, Address(recv_klass, scan_temp, Address::lsl(3))); add(scan_temp, scan_temp, vtable_base); - // Adjust recv_klass by scaled itable_index, so we can free itable_index. - assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); - // lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off)); - lea(recv_klass, Address(recv_klass, itable_index, Address::lsl(3))); - if (itentry_off) - add(recv_klass, recv_klass, itentry_off); + if (return_method) { + // Adjust recv_klass by scaled itable_index, so we can free itable_index. + assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); + // lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off)); + lea(recv_klass, Address(recv_klass, itable_index, Address::lsl(3))); + if (itentry_off) + add(recv_klass, recv_klass, itentry_off); + } // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { // if (scan->interface() == intf) { @@ -1021,8 +1027,10 @@ bind(found_method); // Got a hit. - ldr(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes())); - ldr(method_result, Address(recv_klass, scan_temp)); + if (return_method) { + ldrw(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes())); + ldr(method_result, Address(recv_klass, scan_temp, Address::uxtw(0))); + } } // virtual method calling diff -r 67abfee27e69 -r 7c03f19d38a7 src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp Mon Jan 22 12:00:41 2018 +0800 +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp Fri Jan 19 16:57:56 2018 +0000 @@ -875,7 +875,8 @@ RegisterOrConstant itable_index, Register method_result, Register scan_temp, - Label& no_such_interface); + Label& no_such_interface, + bool return_method = true); // virtual method calling // n.b. x86 allows RegisterOrConstant for vtable_index diff -r 67abfee27e69 -r 7c03f19d38a7 src/hotspot/cpu/aarch64/templateTable_aarch64.cpp --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp Mon Jan 22 12:00:41 2018 +0800 +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp Fri Jan 19 16:57:56 2018 +0000 @@ -3279,11 +3279,11 @@ transition(vtos, vtos); assert(byte_no == f1_byte, "use this argument"); - prepare_invoke(byte_no, r0, rmethod, // get f1 Klass*, f2 itable index + prepare_invoke(byte_no, r0, rmethod, // get f1 Klass*, f2 Method* r2, r3); // recv, flags // r0: interface klass (from f1) - // rmethod: itable index (from f2) + // rmethod: method (from f2) // r2: receiver // r3: flags @@ -3302,10 +3302,27 @@ __ null_check(r2, oopDesc::klass_offset_in_bytes()); __ load_klass(r3, r2); + Label no_such_interface, no_such_method; + + // Receiver subtype check against REFC. + // Superklass in r0. Subklass in r3. Blows rscratch2, r13 + __ lookup_interface_method(// inputs: rec. class, interface, itable index + r3, r0, noreg, + // outputs: scan temp. reg, scan temp. reg + rscratch2, r13, + no_such_interface, + /*return_method=*/false); + // profile this call __ profile_virtual_call(r3, r13, r19); - Label no_such_interface, no_such_method; + // Get declaring interface class from method, and itable index + __ ldr(r0, Address(rmethod, Method::const_offset())); + __ ldr(r0, Address(r0, ConstMethod::constants_offset())); + __ ldr(r0, Address(r0, ConstantPool::pool_holder_offset_in_bytes())); + __ ldrw(rmethod, Address(rmethod, Method::itable_index_offset())); + __ subw(rmethod, rmethod, Method::itable_index_max); + __ negw(rmethod, rmethod); __ lookup_interface_method(// inputs: rec. class, interface, itable index r3, r0, rmethod, diff -r 67abfee27e69 -r 7c03f19d38a7 src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp --- a/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp Mon Jan 22 12:00:41 2018 +0800 +++ b/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp Fri Jan 19 16:57:56 2018 +0000 @@ -29,6 +29,7 @@ #include "code/vtableStubs.hpp" #include "interp_masm_aarch64.hpp" #include "memory/resourceArea.hpp" +#include "oops/compiledICHolder.hpp" #include "oops/instanceKlass.hpp" #include "oops/klassVtable.hpp" #include "runtime/sharedRuntime.hpp" @@ -140,28 +141,44 @@ #endif // Entry arguments: - // rscratch2: Interface + // rscratch2: CompiledICHolder // j_rarg0: Receiver - // Free registers (non-args) are r0 (interface), rmethod + + // Most registers are in use; we'll use r0, rmethod, r10, r11 + const Register recv_klass_reg = r10; + const Register holder_klass_reg = r0; // declaring interface klass (DECC) + const Register resolved_klass_reg = rmethod; // resolved interface klass (REFC) + const Register temp_reg = r11; + const Register icholder_reg = rscratch2; + + Label L_no_such_interface; + + __ ldr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset())); + __ ldr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset())); // get receiver (need to skip return address on top of stack) - assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); // get receiver klass (also an implicit null-check) address npe_addr = __ pc(); - - // Most registers are in use; we'll use r0, rmethod, r10, r11 - __ load_klass(r10, j_rarg0); - - Label throw_icce; + __ load_klass(recv_klass_reg, j_rarg0); - // Get Method* and entrypoint for compiler + // Receiver subtype check against REFC. + // Destroys recv_klass_reg value. + __ lookup_interface_method(// inputs: rec. class, interface + recv_klass_reg, resolved_klass_reg, noreg, + // outputs: scan temp. reg1, scan temp. reg2 + recv_klass_reg, temp_reg, + L_no_such_interface, + /*return_method=*/false); + + // Get selected method from declaring class and itable index + __ load_klass(recv_klass_reg, j_rarg0); // restore recv_klass_reg __ lookup_interface_method(// inputs: rec. class, interface, itable index - r10, rscratch2, itable_index, - // outputs: method, scan temp. reg - rmethod, r11, - throw_icce); + recv_klass_reg, holder_klass_reg, itable_index, + // outputs: method, scan temp. reg + rmethod, temp_reg, + L_no_such_interface); // method (rmethod): Method* // j_rarg0: receiver @@ -183,7 +200,7 @@ __ ldr(rscratch1, Address(rmethod, Method::from_compiled_offset())); __ br(rscratch1); - __ bind(throw_icce); + __ bind(L_no_such_interface); __ far_jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); __ flush(); @@ -205,11 +222,11 @@ int size = DebugVtables ? 216 : 0; if (CountCompiledCalls) size += 6 * 4; - // FIXME + // FIXME: vtable stubs only need 36 bytes if (is_vtable_stub) size += 52; else - size += 104; + size += 176; return size; // In order to tune these parameters, run the JVM with VM options @@ -217,33 +234,58 @@ // actual itable stubs. Run it with -Xmx31G -XX:+UseCompressedOops. // // If Universe::narrow_klass_base is nonzero, decoding a compressed - // class can take zeveral instructions. Run it with -Xmx31G - // -XX:+UseCompressedOops. + // class can take zeveral instructions. // // The JVM98 app. _202_jess has a megamorphic interface call. // The itable code looks like this: - // Decoding VtableStub itbl[1]@12 - // ldr w10, [x1,#8] - // lsl x10, x10, #3 - // ldr w11, [x10,#280] - // add x11, x10, x11, uxtx #3 - // add x11, x11, #0x1b8 - // ldr x12, [x11] - // cmp x9, x12 - // b.eq success - // loop: - // cbz x12, throw_icce - // add x11, x11, #0x10 - // ldr x12, [x11] - // cmp x9, x12 - // b.ne loop - // success: - // ldr x11, [x11,#8] - // ldr x12, [x10,x11] - // ldr x8, [x12,#72] - // br x8 - // throw_icce: - // b throw_ICCE_entry + + // ldr xmethod, [xscratch2,#CompiledICHolder::holder_klass_offset] + // ldr x0, [xscratch2] + // ldr w10, [x1,#oopDesc::klass_offset_in_bytes] + // mov xheapbase, #0x3c000000 // #narrow_klass_base + // movk xheapbase, #0x3f7, lsl #32 + // add x10, xheapbase, x10 + // mov xheapbase, #0xe7ff0000 // #heapbase + // movk xheapbase, #0x3f7, lsl #32 + // ldr w11, [x10,#vtable_length_offset] + // add x11, x10, x11, uxtx #3 + // add x11, x11, #itableMethodEntry::method_offset_in_bytes + // ldr x10, [x11] + // cmp xmethod, x10 + // b.eq found_method + // search: + // cbz x10, no_such_interface + // add x11, x11, #0x10 + // ldr x10, [x11] + // cmp xmethod, x10 + // b.ne search + // found_method: + // ldr w10, [x1,#oopDesc::klass_offset_in_bytes] + // mov xheapbase, #0x3c000000 // #narrow_klass_base + // movk xheapbase, #0x3f7, lsl #32 + // add x10, xheapbase, x10 + // mov xheapbase, #0xe7ff0000 // #heapbase + // movk xheapbase, #0x3f7, lsl #32 + // ldr w11, [x10,#vtable_length_offset] + // add x11, x10, x11, uxtx #3 + // add x11, x11, #itableMethodEntry::method_offset_in_bytes + // add x10, x10, #itentry_off + // ldr xmethod, [x11] + // cmp x0, xmethod + // b.eq found_method2 + // search2: + // cbz xmethod, 0x000003ffa872e6cc + // add x11, x11, #0x10 + // ldr xmethod, [x11] + // cmp x0, xmethod + // b.ne search2 + // found_method2: + // ldr w11, [x11,#itableOffsetEntry::offset_offset_in_bytes] + // ldr xmethod, [x10,w11,uxtw] + // ldr xscratch1, [xmethod,#Method::from_compiled_offset] + // br xscratch1 + // no_such_interface: + // b throw_ICCE_entry }