From 83d07c58b6961a3c69b48f56b69392378f2c8559 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Mon, 25 Jan 2021 12:39:33 +0800 Subject: [PATCH 1/3] 8260355: AArch64: deoptimization stub should save vector registers This is an AArch64 port of the fix for JDK-8256056 "Deoptimization stub doesn't save vector registers on x86". The problem is that a vector produced by the Vector API may be stored in a register when the deopt blob is called. Because the deopt blob only stores the lower half of vector registers, the full vector object cannot be rematerialized during deoptimization. So the following will crash on AArch64 with current JDK: make test TEST="jdk/incubator/vector" \ JTREG="VM_OPTIONS=-XX:+DeoptimizeALot -XX:DeoptimizeALotInterval=0" The fix is to store the full vector registers by passing save_vectors=true to save_live_registers() in the deopt blob. Because save_live_registers() places the integer registers above the floating registers in the stack frame, RegisterSaver::r0_offset_in_bytes() needs to calculate the SP offset based on whether full vectors were saved, and whether those vectors were NEON or SVE, rather than using a static offset as it does currently. The change to VectorSupport::allocate_vector_payload_helper() is required because we only store the lowest VMReg slot in the oop map. However unlike x86 the vector registers are always saved in a contiguous region of memory, so we can calculate the address of each vector element as an offset from the address of the first slot. X86 handles this in RegisterMap::pd_location() but that won't work on AArch64 because with SVE there isn't a unique VMReg corresponding to each four-byte physical slot in the vector (there are always exactly eight logical VMRegs regardless of the actual vector length). Tested hotspot_all_no_apps and jdk_core. --- .../cpu/aarch64/sharedRuntime_aarch64.cpp | 95 +++++++++++-------- src/hotspot/share/prims/vectorSupport.cpp | 16 +++- 2 files changed, 65 insertions(+), 46 deletions(-) diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 704031ee9b39a..320c974480171 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -83,25 +83,20 @@ class SimpleRuntimeFrame { // FIXME -- this is used by C1 class RegisterSaver { public: - static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors = false); - static void restore_live_registers(MacroAssembler* masm, bool restore_vectors = false); + static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors); + static void restore_live_registers(MacroAssembler* masm, bool restore_vectors); // Offsets into the register save area // Used by deoptimization when it is managing result register // values on its own - static int r0_offset_in_bytes(void) { return (32 + r0->encoding()) * wordSize; } - static int reg_offset_in_bytes(Register r) { return r0_offset_in_bytes() + r->encoding() * wordSize; } - static int rmethod_offset_in_bytes(void) { return reg_offset_in_bytes(rmethod); } - static int rscratch1_offset_in_bytes(void) { return (32 + rscratch1->encoding()) * wordSize; } + static int reg_offset_in_bytes(Register r, bool save_vectors); + static int r0_offset_in_bytes(bool save_vectors) { return reg_offset_in_bytes(r0, save_vectors); } + static int rscratch1_offset_in_bytes(bool save_vectors) { return reg_offset_in_bytes(rscratch1, save_vectors); } static int v0_offset_in_bytes(void) { return 0; } - static int return_offset_in_bytes(void) { return (32 /* floats*/ + 31 /* gregs*/) * wordSize; } - // During deoptimization only the result registers need to be restored, - // all the other values have already been extracted. - static void restore_result_registers(MacroAssembler* masm); - - // Capture info about frame layout + // Capture info about frame layout + // Note this is only correct when not saving full vectors. enum layout { fpu_state_off = 0, fpu_state_end = fpu_state_off + FPUStateSizeInWords - 1, @@ -116,6 +111,30 @@ class RegisterSaver { }; +int RegisterSaver::reg_offset_in_bytes(Register r, bool save_vectors) { + // The integer registers are located above the floating point + // registers in the stack frame pushed by save_live_registers() so the + // offset depends on whether we are saving full vectors, and whether + // those vectors are NEON or SVE. + + int slots_per_vect = FloatRegisterImpl::save_slots_per_register; + +#if COMPILER2_OR_JVMCI + if (save_vectors) { + slots_per_vect = FloatRegisterImpl::slots_per_neon_register; + +#ifdef COMPILER2 + if (Matcher::supports_scalable_vector()) { + slots_per_vect = Matcher::scalable_vector_reg_size(T_FLOAT); + } +#endif + } +#endif + + int r0_offset = (slots_per_vect * FloatRegisterImpl::number_of_registers) * BytesPerInt; + return r0_offset + r->encoding() * wordSize; +} + OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) { bool use_sve = false; int sve_vector_size_in_bytes = 0; @@ -209,23 +228,6 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve } -void RegisterSaver::restore_result_registers(MacroAssembler* masm) { - - // Just restore result register. Only used by deoptimization. By - // now any callee save register that needs to be restored to a c2 - // caller of the deoptee has been extracted into the vframeArray - // and will be stuffed into the c2i adapter we create for later - // restoration so only result registers need to be restored here. - - // Restore fp result register - __ ldrd(v0, Address(sp, v0_offset_in_bytes())); - // Restore integer result register - __ ldr(r0, Address(sp, r0_offset_in_bytes())); - - // Pop all of the register save are off the stack - __ add(sp, sp, align_up(return_offset_in_bytes(), 16)); -} - // Is vector's size (in bytes) bigger than a size saved by default? // 8 bytes vector registers are saved by default on AArch64. bool SharedRuntime::is_wide_vector(int size) { @@ -2161,6 +2163,7 @@ void SharedRuntime::generate_deopt_blob() { int frame_size_in_words; OopMap* map = NULL; OopMapSet *oop_maps = new OopMapSet(); + bool save_vectors = COMPILER2_OR_JVMCI != 0; // ------------- // This code enters when returning to a de-optimized nmethod. A return @@ -2198,7 +2201,7 @@ void SharedRuntime::generate_deopt_blob() { // Prolog for non exception case! // Save everything in sight. - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_vectors); // Normal deoptimization. Save exec mode for unpack_frames. __ movw(rcpool, Deoptimization::Unpack_deopt); // callee-saved @@ -2216,7 +2219,7 @@ void SharedRuntime::generate_deopt_blob() { // return address is the pc describes what bci to do re-execute at // No need to update map as each call to save_live_registers will produce identical oopmap - (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_vectors); __ movw(rcpool, Deoptimization::Unpack_reexecute); // callee-saved __ b(cont); @@ -2235,7 +2238,7 @@ void SharedRuntime::generate_deopt_blob() { uncommon_trap_offset = __ pc() - start; // Save everything in sight. - RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_vectors); // fetch_unroll_info needs to call last_java_frame() Label retaddr; __ set_last_Java_frame(sp, noreg, retaddr, rscratch1); @@ -2292,7 +2295,7 @@ void SharedRuntime::generate_deopt_blob() { // This is a somewhat fragile mechanism. // Save everything in sight. - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_vectors); // Now it is safe to overwrite any register @@ -2373,7 +2376,7 @@ void SharedRuntime::generate_deopt_blob() { __ verify_oop(r0); // Overwrite the result registers with the exception results. - __ str(r0, Address(sp, RegisterSaver::r0_offset_in_bytes())); + __ str(r0, Address(sp, RegisterSaver::r0_offset_in_bytes(save_vectors))); // I think this is useless // __ str(r3, Address(sp, RegisterSaver::r3_offset_in_bytes())); @@ -2382,7 +2385,14 @@ void SharedRuntime::generate_deopt_blob() { // Only register save data is on the stack. // Now restore the result registers. Everything else is either dead // or captured in the vframeArray. - RegisterSaver::restore_result_registers(masm); + + // Restore fp result register + __ ldrd(v0, Address(sp, RegisterSaver::v0_offset_in_bytes())); + // Restore integer result register + __ ldr(r0, Address(sp, RegisterSaver::r0_offset_in_bytes(save_vectors))); + + // Pop all of the register save area off the stack + __ add(sp, sp, frame_size_in_words * wordSize); // All of the register save area has been popped of the stack. Only the // return address remains. @@ -2464,7 +2474,7 @@ void SharedRuntime::generate_deopt_blob() { // Restore frame locals after moving the frame __ strd(v0, Address(sp, RegisterSaver::v0_offset_in_bytes())); - __ str(r0, Address(sp, RegisterSaver::r0_offset_in_bytes())); + __ str(r0, Address(sp, RegisterSaver::r0_offset_in_bytes(save_vectors))); // Call C code. Need thread but NOT official VM entry // crud. We cannot block on this call, no GC can happen. Call should @@ -2492,7 +2502,7 @@ void SharedRuntime::generate_deopt_blob() { // Collect return values __ ldrd(v0, Address(sp, RegisterSaver::v0_offset_in_bytes())); - __ ldr(r0, Address(sp, RegisterSaver::r0_offset_in_bytes())); + __ ldr(r0, Address(sp, RegisterSaver::r0_offset_in_bytes(save_vectors))); // I think this is useless (throwing pc?) // __ ldr(r3, Address(sp, RegisterSaver::r3_offset_in_bytes())); @@ -2852,13 +2862,14 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha MacroAssembler* masm = new MacroAssembler(&buffer); int frame_size_in_words; + bool save_vectors = false; OopMapSet *oop_maps = new OopMapSet(); OopMap* map = NULL; int start = __ offset(); - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_vectors); int frame_complete = __ offset(); @@ -2890,11 +2901,11 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha // get the returned Method* __ get_vm_result_2(rmethod, rthread); - __ str(rmethod, Address(sp, RegisterSaver::reg_offset_in_bytes(rmethod))); + __ str(rmethod, Address(sp, RegisterSaver::reg_offset_in_bytes(rmethod, save_vectors))); // r0 is where we want to jump, overwrite rscratch1 which is saved and scratch - __ str(r0, Address(sp, RegisterSaver::rscratch1_offset_in_bytes())); - RegisterSaver::restore_live_registers(masm); + __ str(r0, Address(sp, RegisterSaver::rscratch1_offset_in_bytes(save_vectors))); + RegisterSaver::restore_live_registers(masm, save_vectors); // We are back the the original state on entry and ready to go. @@ -2904,7 +2915,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha __ bind(pending); - RegisterSaver::restore_live_registers(masm); + RegisterSaver::restore_live_registers(masm, save_vectors); // exception pending => remove activation and forward to exception handler diff --git a/src/hotspot/share/prims/vectorSupport.cpp b/src/hotspot/share/prims/vectorSupport.cpp index be3bb27177e77..fdd9e585cad96 100644 --- a/src/hotspot/share/prims/vectorSupport.cpp +++ b/src/hotspot/share/prims/vectorSupport.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -135,10 +135,18 @@ Handle VectorSupport::allocate_vector_payload_helper(InstanceKlass* ik, frame* f VMReg vreg = VMRegImpl::as_VMReg(location.register_number()); for (int i = 0; i < num_elem; i++) { - int vslot = (i * elem_size) / VMRegImpl::stack_slot_size; - int off = (i * elem_size) % VMRegImpl::stack_slot_size; + bool contiguous = X86_ONLY(false) NOT_X86(true); + address elem_addr; + + if (contiguous) { + elem_addr = reg_map->location(vreg) + (i * elem_size); + } else { + int vslot = (i * elem_size) / VMRegImpl::stack_slot_size; + int off = (i * elem_size) % VMRegImpl::stack_slot_size; + + elem_addr = reg_map->location(vreg->next(vslot)) + off; + } - address elem_addr = reg_map->location(vreg->next(vslot)) + off; init_payload_element(arr, is_mask, elem_bt, i, elem_addr); } } else { From 2364f3dd457b793564e20a5472cd54ec2471200a Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Mon, 1 Feb 2021 16:06:46 +0800 Subject: [PATCH 2/3] Move SVE slot handling to RegisterMap::pd_location --- .../cpu/aarch64/registerMap_aarch64.cpp | 48 ++++++++++++ .../cpu/aarch64/registerMap_aarch64.hpp | 5 +- .../cpu/aarch64/sharedRuntime_aarch64.cpp | 77 ++++++++++--------- src/hotspot/cpu/aarch64/vmreg_aarch64.cpp | 21 ++++- src/hotspot/cpu/aarch64/vmreg_aarch64.hpp | 24 +++++- src/hotspot/cpu/arm/registerMap_arm.hpp | 4 +- src/hotspot/cpu/arm/vmreg_arm.cpp | 6 +- src/hotspot/cpu/ppc/registerMap_ppc.hpp | 4 +- src/hotspot/cpu/ppc/vmreg_ppc.cpp | 6 +- src/hotspot/cpu/s390/registerMap_s390.hpp | 4 +- src/hotspot/cpu/s390/vmreg_s390.cpp | 6 +- src/hotspot/cpu/x86/registerMap_x86.cpp | 5 +- src/hotspot/cpu/x86/registerMap_x86.hpp | 4 +- src/hotspot/cpu/x86/register_x86.hpp | 7 +- src/hotspot/cpu/x86/vmreg_x86.cpp | 23 +++++- src/hotspot/cpu/zero/registerMap_zero.hpp | 4 +- src/hotspot/cpu/zero/vmreg_zero.cpp | 6 +- src/hotspot/share/code/vmreg.hpp | 16 ++-- src/hotspot/share/prims/vectorSupport.cpp | 13 +--- src/hotspot/share/runtime/registerMap.hpp | 12 ++- 20 files changed, 209 insertions(+), 86 deletions(-) create mode 100644 src/hotspot/cpu/aarch64/registerMap_aarch64.cpp diff --git a/src/hotspot/cpu/aarch64/registerMap_aarch64.cpp b/src/hotspot/cpu/aarch64/registerMap_aarch64.cpp new file mode 100644 index 0000000000000..77e9276320f73 --- /dev/null +++ b/src/hotspot/cpu/aarch64/registerMap_aarch64.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Arm Limited. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "runtime/registerMap.hpp" +#include "vmreg_aarch64.inline.hpp" + +address RegisterMap::pd_location(VMReg reg, int slot) const { + if (reg->is_concrete() && slot == 0) { + return NULL; // Should have been handled by base location() + } else if (reg->is_FloatRegister()) { + // Not all physical slots of an SVE register have corresponding + // VMRegs. However they are always saved to the stack in a + // contiguous region of memory so we can calculate the address of + // the upper slots by offsetting from the base address. + int base_reg_enc = (reg->value() - ConcreteRegisterImpl::max_gpr) / + FloatRegisterImpl::max_slots_per_register; + VMReg base_reg = as_FloatRegister(base_reg_enc)->as_VMReg(); + assert(base_reg->is_concrete(), "should be concrete"); + address base_addr = location(base_reg); + slot += reg->value() - base_reg->value(); + if (base_addr != NULL) { + return base_addr + (slot * VMRegImpl::stack_slot_size); + } + } + return NULL; +} diff --git a/src/hotspot/cpu/aarch64/registerMap_aarch64.hpp b/src/hotspot/cpu/aarch64/registerMap_aarch64.hpp index 9283521bf1bd4..042e2615d7dba 100644 --- a/src/hotspot/cpu/aarch64/registerMap_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/registerMap_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -32,8 +32,7 @@ private: // This is the hook for finding a register in an "well-known" location, // such as a register block of a predetermined format. - // Since there is none, we just return NULL. - address pd_location(VMReg reg) const {return NULL;} + address pd_location(VMReg reg, int slot) const; // no PD state to clear or copy: void pd_clear() {} diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 320c974480171..31f558229baad 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -82,18 +82,21 @@ class SimpleRuntimeFrame { // FIXME -- this is used by C1 class RegisterSaver { + const bool _save_vectors; public: - static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors); - static void restore_live_registers(MacroAssembler* masm, bool restore_vectors); + RegisterSaver(bool save_vectors) : _save_vectors(save_vectors) {} + + OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words); + void restore_live_registers(MacroAssembler* masm); // Offsets into the register save area // Used by deoptimization when it is managing result register // values on its own - static int reg_offset_in_bytes(Register r, bool save_vectors); - static int r0_offset_in_bytes(bool save_vectors) { return reg_offset_in_bytes(r0, save_vectors); } - static int rscratch1_offset_in_bytes(bool save_vectors) { return reg_offset_in_bytes(rscratch1, save_vectors); } - static int v0_offset_in_bytes(void) { return 0; } + int reg_offset_in_bytes(Register r); + int r0_offset_in_bytes() { return reg_offset_in_bytes(r0); } + int rscratch1_offset_in_bytes() { return reg_offset_in_bytes(rscratch1); } + int v0_offset_in_bytes(void) { return 0; } // Capture info about frame layout // Note this is only correct when not saving full vectors. @@ -111,7 +114,7 @@ class RegisterSaver { }; -int RegisterSaver::reg_offset_in_bytes(Register r, bool save_vectors) { +int RegisterSaver::reg_offset_in_bytes(Register r) { // The integer registers are located above the floating point // registers in the stack frame pushed by save_live_registers() so the // offset depends on whether we are saving full vectors, and whether @@ -120,7 +123,7 @@ int RegisterSaver::reg_offset_in_bytes(Register r, bool save_vectors) { int slots_per_vect = FloatRegisterImpl::save_slots_per_register; #if COMPILER2_OR_JVMCI - if (save_vectors) { + if (_save_vectors) { slots_per_vect = FloatRegisterImpl::slots_per_neon_register; #ifdef COMPILER2 @@ -135,7 +138,7 @@ int RegisterSaver::reg_offset_in_bytes(Register r, bool save_vectors) { return r0_offset + r->encoding() * wordSize; } -OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) { +OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words) { bool use_sve = false; int sve_vector_size_in_bytes = 0; int sve_vector_size_in_slots = 0; @@ -147,7 +150,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ #endif #if COMPILER2_OR_JVMCI - if (save_vectors) { + if (_save_vectors) { int vect_words = 0; int extra_save_slots_per_register = 0; // Save upper half of vector registers @@ -161,7 +164,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ additional_frame_words += vect_words; } #else - assert(!save_vectors, "vectors are generated only by C2 and JVMCI"); + assert(!_save_vectors, "vectors are generated only by C2 and JVMCI"); #endif int frame_size_in_bytes = align_up(additional_frame_words * wordSize + @@ -176,7 +179,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ // Save Integer and Float registers. __ enter(); - __ push_CPU_state(save_vectors, use_sve, sve_vector_size_in_bytes); + __ push_CPU_state(_save_vectors, use_sve, sve_vector_size_in_bytes); // Set an oopmap for the call site. This oopmap will map all // oop-registers and debug-info registers as callee-saved. This @@ -201,7 +204,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ for (int i = 0; i < FloatRegisterImpl::number_of_registers; i++) { FloatRegister r = as_FloatRegister(i); int sp_offset = 0; - if (save_vectors) { + if (_save_vectors) { sp_offset = use_sve ? (sve_vector_size_in_slots * i) : (FloatRegisterImpl::slots_per_neon_register * i); } else { @@ -214,9 +217,9 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ return oop_map; } -void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) { +void RegisterSaver::restore_live_registers(MacroAssembler* masm) { #ifdef COMPILER2 - __ pop_CPU_state(restore_vectors, Matcher::supports_scalable_vector(), + __ pop_CPU_state(_save_vectors, Matcher::supports_scalable_vector(), Matcher::scalable_vector_reg_size(T_BYTE)); #else #if !INCLUDE_JVMCI @@ -2163,7 +2166,7 @@ void SharedRuntime::generate_deopt_blob() { int frame_size_in_words; OopMap* map = NULL; OopMapSet *oop_maps = new OopMapSet(); - bool save_vectors = COMPILER2_OR_JVMCI != 0; + RegisterSaver reg_save(COMPILER2_OR_JVMCI != 0); // ------------- // This code enters when returning to a de-optimized nmethod. A return @@ -2201,7 +2204,7 @@ void SharedRuntime::generate_deopt_blob() { // Prolog for non exception case! // Save everything in sight. - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_vectors); + map = reg_save.save_live_registers(masm, 0, &frame_size_in_words); // Normal deoptimization. Save exec mode for unpack_frames. __ movw(rcpool, Deoptimization::Unpack_deopt); // callee-saved @@ -2219,7 +2222,7 @@ void SharedRuntime::generate_deopt_blob() { // return address is the pc describes what bci to do re-execute at // No need to update map as each call to save_live_registers will produce identical oopmap - (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_vectors); + (void) reg_save.save_live_registers(masm, 0, &frame_size_in_words); __ movw(rcpool, Deoptimization::Unpack_reexecute); // callee-saved __ b(cont); @@ -2238,7 +2241,7 @@ void SharedRuntime::generate_deopt_blob() { uncommon_trap_offset = __ pc() - start; // Save everything in sight. - RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_vectors); + reg_save.save_live_registers(masm, 0, &frame_size_in_words); // fetch_unroll_info needs to call last_java_frame() Label retaddr; __ set_last_Java_frame(sp, noreg, retaddr, rscratch1); @@ -2295,7 +2298,7 @@ void SharedRuntime::generate_deopt_blob() { // This is a somewhat fragile mechanism. // Save everything in sight. - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_vectors); + map = reg_save.save_live_registers(masm, 0, &frame_size_in_words); // Now it is safe to overwrite any register @@ -2376,7 +2379,7 @@ void SharedRuntime::generate_deopt_blob() { __ verify_oop(r0); // Overwrite the result registers with the exception results. - __ str(r0, Address(sp, RegisterSaver::r0_offset_in_bytes(save_vectors))); + __ str(r0, Address(sp, reg_save.r0_offset_in_bytes())); // I think this is useless // __ str(r3, Address(sp, RegisterSaver::r3_offset_in_bytes())); @@ -2387,9 +2390,9 @@ void SharedRuntime::generate_deopt_blob() { // or captured in the vframeArray. // Restore fp result register - __ ldrd(v0, Address(sp, RegisterSaver::v0_offset_in_bytes())); + __ ldrd(v0, Address(sp, reg_save.v0_offset_in_bytes())); // Restore integer result register - __ ldr(r0, Address(sp, RegisterSaver::r0_offset_in_bytes(save_vectors))); + __ ldr(r0, Address(sp, reg_save.r0_offset_in_bytes())); // Pop all of the register save area off the stack __ add(sp, sp, frame_size_in_words * wordSize); @@ -2473,8 +2476,8 @@ void SharedRuntime::generate_deopt_blob() { __ sub(sp, sp, (frame_size_in_words - 2) * wordSize); // Restore frame locals after moving the frame - __ strd(v0, Address(sp, RegisterSaver::v0_offset_in_bytes())); - __ str(r0, Address(sp, RegisterSaver::r0_offset_in_bytes(save_vectors))); + __ strd(v0, Address(sp, reg_save.v0_offset_in_bytes())); + __ str(r0, Address(sp, reg_save.r0_offset_in_bytes())); // Call C code. Need thread but NOT official VM entry // crud. We cannot block on this call, no GC can happen. Call should @@ -2501,8 +2504,8 @@ void SharedRuntime::generate_deopt_blob() { __ reset_last_Java_frame(true); // Collect return values - __ ldrd(v0, Address(sp, RegisterSaver::v0_offset_in_bytes())); - __ ldr(r0, Address(sp, RegisterSaver::r0_offset_in_bytes(save_vectors))); + __ ldrd(v0, Address(sp, reg_save.v0_offset_in_bytes())); + __ ldr(r0, Address(sp, reg_save.r0_offset_in_bytes())); // I think this is useless (throwing pc?) // __ ldr(r3, Address(sp, RegisterSaver::r3_offset_in_bytes())); @@ -2748,10 +2751,10 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t address call_pc = NULL; int frame_size_in_words; bool cause_return = (poll_type == POLL_AT_RETURN); - bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP); + RegisterSaver reg_save(poll_type == POLL_AT_VECTOR_LOOP /* save_vectors */); // Save Integer and Float registers. - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_vectors); + map = reg_save.save_live_registers(masm, 0, &frame_size_in_words); // The following is basically a call_VM. However, we need the precise // address of the call in order to generate an oopmap. Hence, we do all the @@ -2796,7 +2799,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t // Exception pending - RegisterSaver::restore_live_registers(masm, save_vectors); + reg_save.restore_live_registers(masm); __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); @@ -2828,7 +2831,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t __ bind(no_adjust); // Normal exit, restore registers and exit. - RegisterSaver::restore_live_registers(masm, save_vectors); + reg_save.restore_live_registers(masm); __ ret(lr); @@ -2862,14 +2865,14 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha MacroAssembler* masm = new MacroAssembler(&buffer); int frame_size_in_words; - bool save_vectors = false; + RegisterSaver reg_save(false /* save_vectors */); OopMapSet *oop_maps = new OopMapSet(); OopMap* map = NULL; int start = __ offset(); - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_vectors); + map = reg_save.save_live_registers(masm, 0, &frame_size_in_words); int frame_complete = __ offset(); @@ -2901,11 +2904,11 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha // get the returned Method* __ get_vm_result_2(rmethod, rthread); - __ str(rmethod, Address(sp, RegisterSaver::reg_offset_in_bytes(rmethod, save_vectors))); + __ str(rmethod, Address(sp, reg_save.reg_offset_in_bytes(rmethod))); // r0 is where we want to jump, overwrite rscratch1 which is saved and scratch - __ str(r0, Address(sp, RegisterSaver::rscratch1_offset_in_bytes(save_vectors))); - RegisterSaver::restore_live_registers(masm, save_vectors); + __ str(r0, Address(sp, reg_save.rscratch1_offset_in_bytes())); + reg_save.restore_live_registers(masm); // We are back the the original state on entry and ready to go. @@ -2915,7 +2918,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha __ bind(pending); - RegisterSaver::restore_live_registers(masm, save_vectors); + reg_save.restore_live_registers(masm); // exception pending => remove activation and forward to exception handler diff --git a/src/hotspot/cpu/aarch64/vmreg_aarch64.cpp b/src/hotspot/cpu/aarch64/vmreg_aarch64.cpp index 1cf7bdb553a17..a3bb9e6bff3df 100644 --- a/src/hotspot/cpu/aarch64/vmreg_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vmreg_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -60,7 +60,24 @@ VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { switch(type) { case INTEGER_TYPE: return ::as_Register(index)->as_VMReg(); case VECTOR_TYPE: return ::as_FloatRegister(index)->as_VMReg(); - case STACK_TYPE: return VMRegImpl::stack2reg(index LP64_ONLY(* 2)); + case STACK_TYPE: return VMRegImpl::stack2reg(index * 2); } return VMRegImpl::Bad(); } + +bool VMRegImpl::is_expressible(int slot_delta) { + if (is_FloatRegister()) { + int enc = ((value() + slot_delta - ConcreteRegisterImpl::max_gpr) + / FloatRegisterImpl::max_slots_per_register); + return as_FloatRegister()->encoding() == enc; + } else if (is_PRegister()) { + int enc = ((value() + slot_delta - ConcreteRegisterImpl::max_fpr) + / PRegisterImpl::max_slots_per_register); + return as_PRegister()->encoding() == enc; + } else if (is_Register()) { + int enc = (value() + slot_delta) / RegisterImpl::max_slots_per_register; + return as_Register()->encoding() == enc; + } else { + return is_stack(); + } +} diff --git a/src/hotspot/cpu/aarch64/vmreg_aarch64.hpp b/src/hotspot/cpu/aarch64/vmreg_aarch64.hpp index 12fab035e0c1a..b16202795be01 100644 --- a/src/hotspot/cpu/aarch64/vmreg_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vmreg_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -34,8 +34,11 @@ inline bool is_FloatRegister() { return value() >= ConcreteRegisterImpl::max_gpr && value() < ConcreteRegisterImpl::max_fpr; } -inline Register as_Register() { +inline bool is_PRegister() { + return value() >= ConcreteRegisterImpl::max_fpr && value() < ConcreteRegisterImpl::max_pr; +} +inline Register as_Register() { assert( is_Register(), "must be"); // Yuk return ::as_Register(value() / RegisterImpl::max_slots_per_register); @@ -48,9 +51,22 @@ inline FloatRegister as_FloatRegister() { FloatRegisterImpl::max_slots_per_register); } -inline bool is_concrete() { +inline PRegister as_PRegister() { + assert( is_PRegister(), "must be" ); + return ::as_PRegister((value() - ConcreteRegisterImpl::max_fpr) / + PRegisterImpl::max_slots_per_register); +} + +inline bool is_concrete() { assert(is_reg(), "must be"); - return is_even(value()); + if (is_FloatRegister()) { + int base = value() - ConcreteRegisterImpl::max_gpr; + return base % FloatRegisterImpl::max_slots_per_register == 0; + } else if (is_PRegister()) { + return true; // Single slot + } else { + return is_even(value()); + } } #endif // CPU_AARCH64_VMREG_AARCH64_HPP diff --git a/src/hotspot/cpu/arm/registerMap_arm.hpp b/src/hotspot/cpu/arm/registerMap_arm.hpp index 08a339cd14b04..bfd49b90e495a 100644 --- a/src/hotspot/cpu/arm/registerMap_arm.hpp +++ b/src/hotspot/cpu/arm/registerMap_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ // Since there is none, we just return NULL. // See registerMap_sparc.hpp for an example of grabbing registers // from register save areas of a standard layout. - address pd_location(VMReg reg) const {return NULL;} + address pd_location(VMReg reg, int slot) const {return NULL;} // no PD state to clear or copy: void pd_clear() {} diff --git a/src/hotspot/cpu/arm/vmreg_arm.cpp b/src/hotspot/cpu/arm/vmreg_arm.cpp index aad0b52663f9a..19c39cff18488 100644 --- a/src/hotspot/cpu/arm/vmreg_arm.cpp +++ b/src/hotspot/cpu/arm/vmreg_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,3 +54,7 @@ VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { Unimplemented(); return VMRegImpl::Bad(); } + +bool VMRegImpl::is_expressible(int slot_delta) { + return true; +} diff --git a/src/hotspot/cpu/ppc/registerMap_ppc.hpp b/src/hotspot/cpu/ppc/registerMap_ppc.hpp index 973e9a3216935..a34ad3043bb50 100644 --- a/src/hotspot/cpu/ppc/registerMap_ppc.hpp +++ b/src/hotspot/cpu/ppc/registerMap_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -33,7 +33,7 @@ // This is the hook for finding a register in an "well-known" location, // such as a register block of a predetermined format. // Since there is none, we just return NULL. - address pd_location(VMReg reg) const { return NULL; } + address pd_location(VMReg reg, int slot) const { return NULL; } // no PD state to clear or copy: void pd_clear() {} diff --git a/src/hotspot/cpu/ppc/vmreg_ppc.cpp b/src/hotspot/cpu/ppc/vmreg_ppc.cpp index be7a435c9bbab..f0b180571e010 100644 --- a/src/hotspot/cpu/ppc/vmreg_ppc.cpp +++ b/src/hotspot/cpu/ppc/vmreg_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -53,3 +53,7 @@ VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { Unimplemented(); return VMRegImpl::Bad(); } + +bool VMRegImpl::is_expressible(int slot_delta) { + return true; +} diff --git a/src/hotspot/cpu/s390/registerMap_s390.hpp b/src/hotspot/cpu/s390/registerMap_s390.hpp index d2d60bce9255e..fd6a23020c494 100644 --- a/src/hotspot/cpu/s390/registerMap_s390.hpp +++ b/src/hotspot/cpu/s390/registerMap_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -34,7 +34,7 @@ // This is the hook for finding a register in a "well-known" location, // such as a register block of a predetermined format. // Since there is none, we just return NULL. - address pd_location(VMReg reg) const {return NULL;} + address pd_location(VMReg reg, int slot) const {return NULL;} // No PD state to clear or copy. void pd_clear() {} diff --git a/src/hotspot/cpu/s390/vmreg_s390.cpp b/src/hotspot/cpu/s390/vmreg_s390.cpp index 81176561bdbb5..d76646fd11833 100644 --- a/src/hotspot/cpu/s390/vmreg_s390.cpp +++ b/src/hotspot/cpu/s390/vmreg_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -52,3 +52,7 @@ VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { Unimplemented(); return VMRegImpl::Bad(); } + +bool VMRegImpl::is_expressible(int slot_delta) { + return true; +} diff --git a/src/hotspot/cpu/x86/registerMap_x86.cpp b/src/hotspot/cpu/x86/registerMap_x86.cpp index fd091262c297a..b6eaeb682eac7 100644 --- a/src/hotspot/cpu/x86/registerMap_x86.cpp +++ b/src/hotspot/cpu/x86/registerMap_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,8 @@ #include "runtime/registerMap.hpp" #include "vmreg_x86.inline.hpp" -address RegisterMap::pd_location(VMReg reg) const { +address RegisterMap::pd_location(VMReg reg, int slot) const { + assert(slot == 0, "unexpected"); if (reg->is_XMMRegister()) { int reg_base = reg->value() - ConcreteRegisterImpl::max_fpr; int base_reg_enc = (reg_base / XMMRegisterImpl::max_slots_per_register); diff --git a/src/hotspot/cpu/x86/registerMap_x86.hpp b/src/hotspot/cpu/x86/registerMap_x86.hpp index 7806c5a71c0d9..bf3460b89a776 100644 --- a/src/hotspot/cpu/x86/registerMap_x86.hpp +++ b/src/hotspot/cpu/x86/registerMap_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ private: // This is the hook for finding a register in an "well-known" location, // such as a register block of a predetermined format. - address pd_location(VMReg reg) const; + address pd_location(VMReg reg, int slot) const; // no PD state to clear or copy: void pd_clear() {} void pd_initialize() {} diff --git a/src/hotspot/cpu/x86/register_x86.hpp b/src/hotspot/cpu/x86/register_x86.hpp index 1461742ba305c..b12eb13506f49 100644 --- a/src/hotspot/cpu/x86/register_x86.hpp +++ b/src/hotspot/cpu/x86/register_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,7 +105,8 @@ inline FloatRegister as_FloatRegister(int encoding) { class FloatRegisterImpl: public AbstractRegisterImpl { public: enum { - number_of_registers = 8 + number_of_registers = 8, + max_slots_per_register = 2 }; // construction @@ -257,7 +258,7 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl { // it's optoregs. number_of_registers = RegisterImpl::number_of_registers * RegisterImpl::max_slots_per_register + - 2 * FloatRegisterImpl::number_of_registers + + FloatRegisterImpl::max_slots_per_register * FloatRegisterImpl::number_of_registers + XMMRegisterImpl::max_slots_per_register * XMMRegisterImpl::number_of_registers + KRegisterImpl::number_of_registers + // mask registers 1 // eflags diff --git a/src/hotspot/cpu/x86/vmreg_x86.cpp b/src/hotspot/cpu/x86/vmreg_x86.cpp index 2519a04bf3e3f..4b689ac902178 100644 --- a/src/hotspot/cpu/x86/vmreg_x86.cpp +++ b/src/hotspot/cpu/x86/vmreg_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,3 +80,24 @@ VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { } return VMRegImpl::Bad(); } + +bool VMRegImpl::is_expressible(int slot_delta) { + if (is_Register()) { + int enc = (value() + slot_delta) / RegisterImpl::max_slots_per_register; + return as_Register()->encoding() == enc; + } else if (is_FloatRegister()) { + int enc = ((value() + slot_delta - ConcreteRegisterImpl::max_gpr) / + FloatRegisterImpl::max_slots_per_register); + return as_FloatRegister()->encoding() == enc; + } else if (is_XMMRegister()) { + int enc = ((value() + slot_delta - ConcreteRegisterImpl::max_fpr) / + XMMRegisterImpl::max_slots_per_register); + return as_XMMRegister()->encoding() == enc; + } else if (is_KRegister()) { + int enc = ((value() + slot_delta - ConcreteRegisterImpl::max_xmm) / + KRegisterImpl::max_slots_per_register); + return as_KRegister()->encoding() == enc; + } else { + return is_stack(); + } +} diff --git a/src/hotspot/cpu/zero/registerMap_zero.hpp b/src/hotspot/cpu/zero/registerMap_zero.hpp index 1110b68b165be..bb6af41d1d403 100644 --- a/src/hotspot/cpu/zero/registerMap_zero.hpp +++ b/src/hotspot/cpu/zero/registerMap_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ // This is the hook for finding a register in an "well-known" location, // such as a register block of a predetermined format. // Since there is none, we just return NULL. - address pd_location(VMReg reg) const { return NULL; } + address pd_location(VMReg reg, int slot) const { return NULL; } // no PD state to clear or copy: void pd_clear() {} diff --git a/src/hotspot/cpu/zero/vmreg_zero.cpp b/src/hotspot/cpu/zero/vmreg_zero.cpp index 3e5d49621d2fc..7b68d26062245 100644 --- a/src/hotspot/cpu/zero/vmreg_zero.cpp +++ b/src/hotspot/cpu/zero/vmreg_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright 2007 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -66,3 +66,7 @@ VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { ShouldNotCallThis(); return VMRegImpl::Bad(); } + +bool VMRegImpl::is_expressible(int slot_delta) { + return true; +} diff --git a/src/hotspot/share/code/vmreg.hpp b/src/hotspot/share/code/vmreg.hpp index 1d4c93649bcbd..93116c160e5a6 100644 --- a/src/hotspot/share/code/vmreg.hpp +++ b/src/hotspot/share/code/vmreg.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,21 +92,21 @@ friend class OptoReg; static const int stack_slot_size; static const int slots_per_word; + // Platform dependent function that returns true if offsetting this + // VMReg by slot_delta slots gives another valid VMReg which is part + // of the same physical register. + bool is_expressible(int slot_delta); - // This really ought to check that the register is "real" in the sense that - // we don't try and get the VMReg number of a physical register that doesn't - // have an expressible part. That would be pd specific code VMReg next() { - assert((is_reg() && value() < stack0->value() - 1) || is_stack(), "must be"); - return (VMReg)(intptr_t)(value() + 1); + return next(1); } VMReg next(int i) { assert((is_reg() && value() < stack0->value() - i) || is_stack(), "must be"); + assert(is_expressible(i), "not expressible"); return (VMReg)(intptr_t)(value() + i); } VMReg prev() { - assert((is_stack() && value() > stack0->value()) || (is_reg() && value() != 0), "must be"); - return (VMReg)(intptr_t)(value() - 1); + return next(-1); } diff --git a/src/hotspot/share/prims/vectorSupport.cpp b/src/hotspot/share/prims/vectorSupport.cpp index fdd9e585cad96..b47cb2d5d16f3 100644 --- a/src/hotspot/share/prims/vectorSupport.cpp +++ b/src/hotspot/share/prims/vectorSupport.cpp @@ -135,17 +135,10 @@ Handle VectorSupport::allocate_vector_payload_helper(InstanceKlass* ik, frame* f VMReg vreg = VMRegImpl::as_VMReg(location.register_number()); for (int i = 0; i < num_elem; i++) { - bool contiguous = X86_ONLY(false) NOT_X86(true); - address elem_addr; + int vslot = (i * elem_size) / VMRegImpl::stack_slot_size; + int off = (i * elem_size) % VMRegImpl::stack_slot_size; - if (contiguous) { - elem_addr = reg_map->location(vreg) + (i * elem_size); - } else { - int vslot = (i * elem_size) / VMRegImpl::stack_slot_size; - int off = (i * elem_size) % VMRegImpl::stack_slot_size; - - elem_addr = reg_map->location(vreg->next(vslot)) + off; - } + address elem_addr = reg_map->location(vreg, vslot) + off; init_payload_element(arr, is_mask, elem_bt, i, elem_addr); } diff --git a/src/hotspot/share/runtime/registerMap.hpp b/src/hotspot/share/runtime/registerMap.hpp index 0ca09d07ce432..7425a3e87210b 100644 --- a/src/hotspot/share/runtime/registerMap.hpp +++ b/src/hotspot/share/runtime/registerMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,7 +95,15 @@ class RegisterMap : public StackObj { if (_location_valid[index] & ((LocationValidType)1 << (reg->value() % location_valid_type_size))) { return (address) _location[reg->value()]; } else { - return pd_location(reg); + return pd_location(reg, 0); + } + } + + address location(VMReg reg, int slot) { + if (reg->is_expressible(slot)) { + return location(reg->next(slot)); + } else { + return pd_location(reg, slot); } } From 0809ccf1bfd624b684f6080650a8aa68dc1feda7 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Tue, 2 Feb 2021 17:11:32 +0800 Subject: [PATCH 3/3] Review comments --- .../cpu/aarch64/registerMap_aarch64.cpp | 24 +++++++++---------- .../cpu/aarch64/registerMap_aarch64.hpp | 3 ++- .../cpu/aarch64/sharedRuntime_aarch64.cpp | 4 ++-- src/hotspot/cpu/aarch64/vmreg_aarch64.cpp | 21 ++-------------- src/hotspot/cpu/arm/registerMap_arm.hpp | 6 ++++- src/hotspot/cpu/arm/vmreg_arm.cpp | 6 +---- src/hotspot/cpu/ppc/registerMap_ppc.hpp | 6 ++++- src/hotspot/cpu/ppc/vmreg_ppc.cpp | 6 +---- src/hotspot/cpu/s390/registerMap_s390.hpp | 6 ++++- src/hotspot/cpu/s390/vmreg_s390.cpp | 6 +---- src/hotspot/cpu/x86/registerMap_x86.cpp | 7 ++++-- src/hotspot/cpu/x86/registerMap_x86.hpp | 3 ++- src/hotspot/cpu/x86/register_x86.hpp | 7 +++--- src/hotspot/cpu/x86/vmreg_x86.cpp | 23 +----------------- src/hotspot/cpu/zero/registerMap_zero.hpp | 6 ++++- src/hotspot/cpu/zero/vmreg_zero.cpp | 6 +---- src/hotspot/share/code/vmreg.hpp | 16 ++++++------- src/hotspot/share/prims/vectorSupport.cpp | 3 +-- src/hotspot/share/runtime/registerMap.hpp | 10 ++++---- 19 files changed, 67 insertions(+), 102 deletions(-) diff --git a/src/hotspot/cpu/aarch64/registerMap_aarch64.cpp b/src/hotspot/cpu/aarch64/registerMap_aarch64.cpp index 77e9276320f73..18e55fa034844 100644 --- a/src/hotspot/cpu/aarch64/registerMap_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/registerMap_aarch64.cpp @@ -26,23 +26,23 @@ #include "runtime/registerMap.hpp" #include "vmreg_aarch64.inline.hpp" -address RegisterMap::pd_location(VMReg reg, int slot) const { - if (reg->is_concrete() && slot == 0) { - return NULL; // Should have been handled by base location() - } else if (reg->is_FloatRegister()) { +address RegisterMap::pd_location(VMReg base_reg, int slot_idx) const { + if (base_reg->is_FloatRegister()) { // Not all physical slots of an SVE register have corresponding // VMRegs. However they are always saved to the stack in a // contiguous region of memory so we can calculate the address of // the upper slots by offsetting from the base address. - int base_reg_enc = (reg->value() - ConcreteRegisterImpl::max_gpr) / + assert(base_reg->is_concrete(), "must pass base reg"); + int base_reg_enc = (base_reg->value() - ConcreteRegisterImpl::max_gpr) / FloatRegisterImpl::max_slots_per_register; - VMReg base_reg = as_FloatRegister(base_reg_enc)->as_VMReg(); - assert(base_reg->is_concrete(), "should be concrete"); - address base_addr = location(base_reg); - slot += reg->value() - base_reg->value(); - if (base_addr != NULL) { - return base_addr + (slot * VMRegImpl::stack_slot_size); + intptr_t offset_in_bytes = slot_idx * VMRegImpl::stack_slot_size; + address base_location = location(base_reg); + if (base_location != NULL) { + return base_location + offset_in_bytes; + } else { + return NULL; } + } else { + return location(base_reg->next(slot_idx)); } - return NULL; } diff --git a/src/hotspot/cpu/aarch64/registerMap_aarch64.hpp b/src/hotspot/cpu/aarch64/registerMap_aarch64.hpp index 042e2615d7dba..1f84b4d2d3e79 100644 --- a/src/hotspot/cpu/aarch64/registerMap_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/registerMap_aarch64.hpp @@ -32,7 +32,8 @@ private: // This is the hook for finding a register in an "well-known" location, // such as a register block of a predetermined format. - address pd_location(VMReg reg, int slot) const; + address pd_location(VMReg reg) const { return NULL; } + address pd_location(VMReg base_reg, int slot_idx) const; // no PD state to clear or copy: void pd_clear() {} diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 31f558229baad..74e84964a164d 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -223,9 +223,9 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm) { Matcher::scalable_vector_reg_size(T_BYTE)); #else #if !INCLUDE_JVMCI - assert(!restore_vectors, "vectors are generated only by C2 and JVMCI"); + assert(!_save_vectors, "vectors are generated only by C2 and JVMCI"); #endif - __ pop_CPU_state(restore_vectors); + __ pop_CPU_state(_save_vectors); #endif __ leave(); diff --git a/src/hotspot/cpu/aarch64/vmreg_aarch64.cpp b/src/hotspot/cpu/aarch64/vmreg_aarch64.cpp index a3bb9e6bff3df..1cf7bdb553a17 100644 --- a/src/hotspot/cpu/aarch64/vmreg_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vmreg_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -60,24 +60,7 @@ VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { switch(type) { case INTEGER_TYPE: return ::as_Register(index)->as_VMReg(); case VECTOR_TYPE: return ::as_FloatRegister(index)->as_VMReg(); - case STACK_TYPE: return VMRegImpl::stack2reg(index * 2); + case STACK_TYPE: return VMRegImpl::stack2reg(index LP64_ONLY(* 2)); } return VMRegImpl::Bad(); } - -bool VMRegImpl::is_expressible(int slot_delta) { - if (is_FloatRegister()) { - int enc = ((value() + slot_delta - ConcreteRegisterImpl::max_gpr) - / FloatRegisterImpl::max_slots_per_register); - return as_FloatRegister()->encoding() == enc; - } else if (is_PRegister()) { - int enc = ((value() + slot_delta - ConcreteRegisterImpl::max_fpr) - / PRegisterImpl::max_slots_per_register); - return as_PRegister()->encoding() == enc; - } else if (is_Register()) { - int enc = (value() + slot_delta) / RegisterImpl::max_slots_per_register; - return as_Register()->encoding() == enc; - } else { - return is_stack(); - } -} diff --git a/src/hotspot/cpu/arm/registerMap_arm.hpp b/src/hotspot/cpu/arm/registerMap_arm.hpp index bfd49b90e495a..9f7631244b369 100644 --- a/src/hotspot/cpu/arm/registerMap_arm.hpp +++ b/src/hotspot/cpu/arm/registerMap_arm.hpp @@ -34,7 +34,11 @@ // Since there is none, we just return NULL. // See registerMap_sparc.hpp for an example of grabbing registers // from register save areas of a standard layout. - address pd_location(VMReg reg, int slot) const {return NULL;} + address pd_location(VMReg reg) const {return NULL;} + + address pd_location(VMReg base_reg, int slot_idx) const { + return location(base_reg->next(slot_idx)); + } // no PD state to clear or copy: void pd_clear() {} diff --git a/src/hotspot/cpu/arm/vmreg_arm.cpp b/src/hotspot/cpu/arm/vmreg_arm.cpp index 19c39cff18488..aad0b52663f9a 100644 --- a/src/hotspot/cpu/arm/vmreg_arm.cpp +++ b/src/hotspot/cpu/arm/vmreg_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,3 @@ VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { Unimplemented(); return VMRegImpl::Bad(); } - -bool VMRegImpl::is_expressible(int slot_delta) { - return true; -} diff --git a/src/hotspot/cpu/ppc/registerMap_ppc.hpp b/src/hotspot/cpu/ppc/registerMap_ppc.hpp index a34ad3043bb50..567028fa3e8a4 100644 --- a/src/hotspot/cpu/ppc/registerMap_ppc.hpp +++ b/src/hotspot/cpu/ppc/registerMap_ppc.hpp @@ -33,7 +33,11 @@ // This is the hook for finding a register in an "well-known" location, // such as a register block of a predetermined format. // Since there is none, we just return NULL. - address pd_location(VMReg reg, int slot) const { return NULL; } + address pd_location(VMReg reg) const { return NULL; } + + address pd_location(VMReg base_reg, int slot_idx) const { + return location(base_reg->next(slot_idx)); + } // no PD state to clear or copy: void pd_clear() {} diff --git a/src/hotspot/cpu/ppc/vmreg_ppc.cpp b/src/hotspot/cpu/ppc/vmreg_ppc.cpp index f0b180571e010..be7a435c9bbab 100644 --- a/src/hotspot/cpu/ppc/vmreg_ppc.cpp +++ b/src/hotspot/cpu/ppc/vmreg_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -53,7 +53,3 @@ VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { Unimplemented(); return VMRegImpl::Bad(); } - -bool VMRegImpl::is_expressible(int slot_delta) { - return true; -} diff --git a/src/hotspot/cpu/s390/registerMap_s390.hpp b/src/hotspot/cpu/s390/registerMap_s390.hpp index fd6a23020c494..6fa7a5a12da72 100644 --- a/src/hotspot/cpu/s390/registerMap_s390.hpp +++ b/src/hotspot/cpu/s390/registerMap_s390.hpp @@ -34,7 +34,11 @@ // This is the hook for finding a register in a "well-known" location, // such as a register block of a predetermined format. // Since there is none, we just return NULL. - address pd_location(VMReg reg, int slot) const {return NULL;} + address pd_location(VMReg reg) const {return NULL;} + + address pd_location(VMReg base_reg, int slot_idx) const { + return location(base_reg->next(slot_idx)); + } // No PD state to clear or copy. void pd_clear() {} diff --git a/src/hotspot/cpu/s390/vmreg_s390.cpp b/src/hotspot/cpu/s390/vmreg_s390.cpp index d76646fd11833..81176561bdbb5 100644 --- a/src/hotspot/cpu/s390/vmreg_s390.cpp +++ b/src/hotspot/cpu/s390/vmreg_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -52,7 +52,3 @@ VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { Unimplemented(); return VMRegImpl::Bad(); } - -bool VMRegImpl::is_expressible(int slot_delta) { - return true; -} diff --git a/src/hotspot/cpu/x86/registerMap_x86.cpp b/src/hotspot/cpu/x86/registerMap_x86.cpp index b6eaeb682eac7..3acbb98bf76b2 100644 --- a/src/hotspot/cpu/x86/registerMap_x86.cpp +++ b/src/hotspot/cpu/x86/registerMap_x86.cpp @@ -26,8 +26,7 @@ #include "runtime/registerMap.hpp" #include "vmreg_x86.inline.hpp" -address RegisterMap::pd_location(VMReg reg, int slot) const { - assert(slot == 0, "unexpected"); +address RegisterMap::pd_location(VMReg reg) const { if (reg->is_XMMRegister()) { int reg_base = reg->value() - ConcreteRegisterImpl::max_fpr; int base_reg_enc = (reg_base / XMMRegisterImpl::max_slots_per_register); @@ -62,3 +61,7 @@ address RegisterMap::pd_location(VMReg reg, int slot) const { } return NULL; } + +address RegisterMap::pd_location(VMReg base_reg, int slot_idx) const { + return location(base_reg->next(slot_idx)); +} diff --git a/src/hotspot/cpu/x86/registerMap_x86.hpp b/src/hotspot/cpu/x86/registerMap_x86.hpp index bf3460b89a776..8ab259c777c7d 100644 --- a/src/hotspot/cpu/x86/registerMap_x86.hpp +++ b/src/hotspot/cpu/x86/registerMap_x86.hpp @@ -31,7 +31,8 @@ private: // This is the hook for finding a register in an "well-known" location, // such as a register block of a predetermined format. - address pd_location(VMReg reg, int slot) const; + address pd_location(VMReg reg) const; + address pd_location(VMReg base_reg, int slot_idx) const; // no PD state to clear or copy: void pd_clear() {} void pd_initialize() {} diff --git a/src/hotspot/cpu/x86/register_x86.hpp b/src/hotspot/cpu/x86/register_x86.hpp index b12eb13506f49..1461742ba305c 100644 --- a/src/hotspot/cpu/x86/register_x86.hpp +++ b/src/hotspot/cpu/x86/register_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,8 +105,7 @@ inline FloatRegister as_FloatRegister(int encoding) { class FloatRegisterImpl: public AbstractRegisterImpl { public: enum { - number_of_registers = 8, - max_slots_per_register = 2 + number_of_registers = 8 }; // construction @@ -258,7 +257,7 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl { // it's optoregs. number_of_registers = RegisterImpl::number_of_registers * RegisterImpl::max_slots_per_register + - FloatRegisterImpl::max_slots_per_register * FloatRegisterImpl::number_of_registers + + 2 * FloatRegisterImpl::number_of_registers + XMMRegisterImpl::max_slots_per_register * XMMRegisterImpl::number_of_registers + KRegisterImpl::number_of_registers + // mask registers 1 // eflags diff --git a/src/hotspot/cpu/x86/vmreg_x86.cpp b/src/hotspot/cpu/x86/vmreg_x86.cpp index 4b689ac902178..2519a04bf3e3f 100644 --- a/src/hotspot/cpu/x86/vmreg_x86.cpp +++ b/src/hotspot/cpu/x86/vmreg_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,24 +80,3 @@ VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { } return VMRegImpl::Bad(); } - -bool VMRegImpl::is_expressible(int slot_delta) { - if (is_Register()) { - int enc = (value() + slot_delta) / RegisterImpl::max_slots_per_register; - return as_Register()->encoding() == enc; - } else if (is_FloatRegister()) { - int enc = ((value() + slot_delta - ConcreteRegisterImpl::max_gpr) / - FloatRegisterImpl::max_slots_per_register); - return as_FloatRegister()->encoding() == enc; - } else if (is_XMMRegister()) { - int enc = ((value() + slot_delta - ConcreteRegisterImpl::max_fpr) / - XMMRegisterImpl::max_slots_per_register); - return as_XMMRegister()->encoding() == enc; - } else if (is_KRegister()) { - int enc = ((value() + slot_delta - ConcreteRegisterImpl::max_xmm) / - KRegisterImpl::max_slots_per_register); - return as_KRegister()->encoding() == enc; - } else { - return is_stack(); - } -} diff --git a/src/hotspot/cpu/zero/registerMap_zero.hpp b/src/hotspot/cpu/zero/registerMap_zero.hpp index bb6af41d1d403..b7a22a376a543 100644 --- a/src/hotspot/cpu/zero/registerMap_zero.hpp +++ b/src/hotspot/cpu/zero/registerMap_zero.hpp @@ -32,7 +32,11 @@ // This is the hook for finding a register in an "well-known" location, // such as a register block of a predetermined format. // Since there is none, we just return NULL. - address pd_location(VMReg reg, int slot) const { return NULL; } + address pd_location(VMReg reg) const { return NULL; } + + address pd_location(VMReg base_reg, int slot_idx) const { + return location(base_reg->next(slot_idx)); + } // no PD state to clear or copy: void pd_clear() {} diff --git a/src/hotspot/cpu/zero/vmreg_zero.cpp b/src/hotspot/cpu/zero/vmreg_zero.cpp index 7b68d26062245..3e5d49621d2fc 100644 --- a/src/hotspot/cpu/zero/vmreg_zero.cpp +++ b/src/hotspot/cpu/zero/vmreg_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2007 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -66,7 +66,3 @@ VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { ShouldNotCallThis(); return VMRegImpl::Bad(); } - -bool VMRegImpl::is_expressible(int slot_delta) { - return true; -} diff --git a/src/hotspot/share/code/vmreg.hpp b/src/hotspot/share/code/vmreg.hpp index 93116c160e5a6..1d4c93649bcbd 100644 --- a/src/hotspot/share/code/vmreg.hpp +++ b/src/hotspot/share/code/vmreg.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,21 +92,21 @@ friend class OptoReg; static const int stack_slot_size; static const int slots_per_word; - // Platform dependent function that returns true if offsetting this - // VMReg by slot_delta slots gives another valid VMReg which is part - // of the same physical register. - bool is_expressible(int slot_delta); + // This really ought to check that the register is "real" in the sense that + // we don't try and get the VMReg number of a physical register that doesn't + // have an expressible part. That would be pd specific code VMReg next() { - return next(1); + assert((is_reg() && value() < stack0->value() - 1) || is_stack(), "must be"); + return (VMReg)(intptr_t)(value() + 1); } VMReg next(int i) { assert((is_reg() && value() < stack0->value() - i) || is_stack(), "must be"); - assert(is_expressible(i), "not expressible"); return (VMReg)(intptr_t)(value() + i); } VMReg prev() { - return next(-1); + assert((is_stack() && value() > stack0->value()) || (is_reg() && value() != 0), "must be"); + return (VMReg)(intptr_t)(value() - 1); } diff --git a/src/hotspot/share/prims/vectorSupport.cpp b/src/hotspot/share/prims/vectorSupport.cpp index b47cb2d5d16f3..54209834e9552 100644 --- a/src/hotspot/share/prims/vectorSupport.cpp +++ b/src/hotspot/share/prims/vectorSupport.cpp @@ -138,8 +138,7 @@ Handle VectorSupport::allocate_vector_payload_helper(InstanceKlass* ik, frame* f int vslot = (i * elem_size) / VMRegImpl::stack_slot_size; int off = (i * elem_size) % VMRegImpl::stack_slot_size; - address elem_addr = reg_map->location(vreg, vslot) + off; - + address elem_addr = reg_map->location(vreg, vslot) + off; // assumes little endian element order init_payload_element(arr, is_mask, elem_bt, i, elem_addr); } } else { diff --git a/src/hotspot/share/runtime/registerMap.hpp b/src/hotspot/share/runtime/registerMap.hpp index 7425a3e87210b..c37b3f4c1827e 100644 --- a/src/hotspot/share/runtime/registerMap.hpp +++ b/src/hotspot/share/runtime/registerMap.hpp @@ -95,15 +95,15 @@ class RegisterMap : public StackObj { if (_location_valid[index] & ((LocationValidType)1 << (reg->value() % location_valid_type_size))) { return (address) _location[reg->value()]; } else { - return pd_location(reg, 0); + return pd_location(reg); } } - address location(VMReg reg, int slot) { - if (reg->is_expressible(slot)) { - return location(reg->next(slot)); + address location(VMReg base_reg, int slot_idx) const { + if (slot_idx > 0) { + return pd_location(base_reg, slot_idx); } else { - return pd_location(reg, slot); + return location(base_reg); } }