8329258: TailCall should not use frame pointer register for jump target
Co-authored-by: Fei Yang <fyang@openjdk.org> Reviewed-by: rcastanedalo, aph
This commit is contained in:
parent
4a78906db1
commit
cccc95358d
@ -694,6 +694,11 @@ reg_class no_special_ptr_reg %{
|
||||
return _NO_SPECIAL_PTR_REG_mask;
|
||||
%}
|
||||
|
||||
// Class for all non_special pointer registers (excluding rfp)
|
||||
reg_class no_special_no_rfp_ptr_reg %{
|
||||
return _NO_SPECIAL_NO_RFP_PTR_REG_mask;
|
||||
%}
|
||||
|
||||
// Class for all float registers
|
||||
reg_class float_reg(
|
||||
V0,
|
||||
@ -1125,6 +1130,7 @@ extern RegMask _PTR_REG_mask;
|
||||
extern RegMask _NO_SPECIAL_REG32_mask;
|
||||
extern RegMask _NO_SPECIAL_REG_mask;
|
||||
extern RegMask _NO_SPECIAL_PTR_REG_mask;
|
||||
extern RegMask _NO_SPECIAL_NO_RFP_PTR_REG_mask;
|
||||
|
||||
class CallStubImpl {
|
||||
|
||||
@ -1213,6 +1219,7 @@ source %{
|
||||
RegMask _NO_SPECIAL_REG32_mask;
|
||||
RegMask _NO_SPECIAL_REG_mask;
|
||||
RegMask _NO_SPECIAL_PTR_REG_mask;
|
||||
RegMask _NO_SPECIAL_NO_RFP_PTR_REG_mask;
|
||||
|
||||
void reg_mask_init() {
|
||||
// We derive below RegMask(s) from the ones which are auto-generated from
|
||||
@ -1249,6 +1256,9 @@ source %{
|
||||
_NO_SPECIAL_REG_mask.Remove(OptoReg::as_OptoReg(r29->as_VMReg()));
|
||||
_NO_SPECIAL_PTR_REG_mask.Remove(OptoReg::as_OptoReg(r29->as_VMReg()));
|
||||
}
|
||||
|
||||
_NO_SPECIAL_NO_RFP_PTR_REG_mask = _NO_SPECIAL_PTR_REG_mask;
|
||||
_NO_SPECIAL_NO_RFP_PTR_REG_mask.Remove(OptoReg::as_OptoReg(r29->as_VMReg()));
|
||||
}
|
||||
|
||||
// Optimizaton of volatile gets and puts
|
||||
@ -4690,6 +4700,18 @@ operand iRegPNoSp()
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
// This operand is not allowed to use rfp even if
|
||||
// rfp is not used to hold the frame pointer.
|
||||
operand iRegPNoSpNoRfp()
|
||||
%{
|
||||
constraint(ALLOC_IN_RC(no_special_no_rfp_ptr_reg));
|
||||
match(RegP);
|
||||
match(iRegPNoSp);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
// Pointer 64 bit Register R0 only
|
||||
operand iRegP_R0()
|
||||
%{
|
||||
@ -16087,7 +16109,9 @@ instruct CallLeafNoFPDirect(method meth)
|
||||
// Also known as an 'interprocedural jump'.
|
||||
// Target of jump will eventually return to caller.
|
||||
// TailJump below removes the return address.
|
||||
instruct TailCalljmpInd(iRegPNoSp jump_target, inline_cache_RegP method_ptr)
|
||||
// Don't use rfp for 'jump_target' because a MachEpilogNode has already been
|
||||
// emitted just above the TailCall which has reset rfp to the caller state.
|
||||
instruct TailCalljmpInd(iRegPNoSpNoRfp jump_target, inline_cache_RegP method_ptr)
|
||||
%{
|
||||
match(TailCall jump_target method_ptr);
|
||||
|
||||
@ -16100,7 +16124,7 @@ instruct TailCalljmpInd(iRegPNoSp jump_target, inline_cache_RegP method_ptr)
|
||||
ins_pipe(pipe_class_call);
|
||||
%}
|
||||
|
||||
instruct TailjmpInd(iRegPNoSp jump_target, iRegP_R0 ex_oop)
|
||||
instruct TailjmpInd(iRegPNoSpNoRfp jump_target, iRegP_R0 ex_oop)
|
||||
%{
|
||||
match(TailJump jump_target ex_oop);
|
||||
|
||||
|
@ -649,10 +649,12 @@ reg_class non_allocatable_reg(
|
||||
R23, R23_H // java thread
|
||||
);
|
||||
|
||||
// Class for all non-special integer registers
|
||||
reg_class no_special_reg32 %{
|
||||
return _NO_SPECIAL_REG32_mask;
|
||||
%}
|
||||
|
||||
// Class for all non-special long integer registers
|
||||
reg_class no_special_reg %{
|
||||
return _NO_SPECIAL_REG_mask;
|
||||
%}
|
||||
@ -661,10 +663,16 @@ reg_class ptr_reg %{
|
||||
return _PTR_REG_mask;
|
||||
%}
|
||||
|
||||
// Class for all non_special pointer registers
|
||||
reg_class no_special_ptr_reg %{
|
||||
return _NO_SPECIAL_PTR_REG_mask;
|
||||
%}
|
||||
|
||||
// Class for all non_special pointer registers (excluding fp)
|
||||
reg_class no_special_no_fp_ptr_reg %{
|
||||
return _NO_SPECIAL_NO_FP_PTR_REG_mask;
|
||||
%}
|
||||
|
||||
// Class for 64 bit register r10
|
||||
reg_class r10_reg(
|
||||
R10, R10_H
|
||||
@ -1037,6 +1045,7 @@ extern RegMask _PTR_REG_mask;
|
||||
extern RegMask _NO_SPECIAL_REG32_mask;
|
||||
extern RegMask _NO_SPECIAL_REG_mask;
|
||||
extern RegMask _NO_SPECIAL_PTR_REG_mask;
|
||||
extern RegMask _NO_SPECIAL_NO_FP_PTR_REG_mask;
|
||||
|
||||
class CallStubImpl {
|
||||
|
||||
@ -1099,6 +1108,7 @@ RegMask _PTR_REG_mask;
|
||||
RegMask _NO_SPECIAL_REG32_mask;
|
||||
RegMask _NO_SPECIAL_REG_mask;
|
||||
RegMask _NO_SPECIAL_PTR_REG_mask;
|
||||
RegMask _NO_SPECIAL_NO_FP_PTR_REG_mask;
|
||||
|
||||
void reg_mask_init() {
|
||||
|
||||
@ -1133,6 +1143,9 @@ void reg_mask_init() {
|
||||
_NO_SPECIAL_REG_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg()));
|
||||
_NO_SPECIAL_PTR_REG_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg()));
|
||||
}
|
||||
|
||||
_NO_SPECIAL_NO_FP_PTR_REG_mask = _NO_SPECIAL_PTR_REG_mask;
|
||||
_NO_SPECIAL_NO_FP_PTR_REG_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg()));
|
||||
}
|
||||
|
||||
void PhaseOutput::pd_perform_mach_node_analysis() {
|
||||
@ -3175,6 +3188,18 @@ operand iRegPNoSp()
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
// This operand is not allowed to use fp even if
|
||||
// fp is not used to hold the frame pointer.
|
||||
operand iRegPNoSpNoFp()
|
||||
%{
|
||||
constraint(ALLOC_IN_RC(no_special_no_fp_ptr_reg));
|
||||
match(RegP);
|
||||
match(iRegPNoSp);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand iRegP_R10()
|
||||
%{
|
||||
constraint(ALLOC_IN_RC(r10_reg));
|
||||
@ -10506,7 +10531,9 @@ instruct cmpFastUnlockLightweight(rFlagsReg cr, iRegP object, iRegP_R10 box, iRe
|
||||
// Also known as an 'interprocedural jump'.
|
||||
// Target of jump will eventually return to caller.
|
||||
// TailJump below removes the return address.
|
||||
instruct TailCalljmpInd(iRegPNoSp jump_target, inline_cache_RegP method_oop)
|
||||
// Don't use fp for 'jump_target' because a MachEpilogNode has already been
|
||||
// emitted just above the TailCall which has reset fp to the caller state.
|
||||
instruct TailCalljmpInd(iRegPNoSpNoFp jump_target, inline_cache_RegP method_oop)
|
||||
%{
|
||||
match(TailCall jump_target method_oop);
|
||||
|
||||
@ -10519,7 +10546,7 @@ instruct TailCalljmpInd(iRegPNoSp jump_target, inline_cache_RegP method_oop)
|
||||
ins_pipe(pipe_class_call);
|
||||
%}
|
||||
|
||||
instruct TailjmpInd(iRegPNoSp jump_target, iRegP_R10 ex_oop)
|
||||
instruct TailjmpInd(iRegPNoSpNoFp jump_target, iRegP_R10 ex_oop)
|
||||
%{
|
||||
match(TailJump jump_target ex_oop);
|
||||
|
||||
|
@ -13558,6 +13558,8 @@ instruct Ret() %{
|
||||
// Also known as an 'interprocedural jump'.
|
||||
// Target of jump will eventually return to caller.
|
||||
// TailJump below removes the return address.
|
||||
// Don't use ebp for 'jump_target' because a MachEpilogNode has already been
|
||||
// emitted just above the TailCall which has reset ebp to the caller state.
|
||||
instruct TailCalljmpInd(eRegP_no_EBP jump_target, eBXRegP method_ptr) %{
|
||||
match(TailCall jump_target method_ptr);
|
||||
ins_cost(300);
|
||||
|
@ -12469,6 +12469,8 @@ instruct Ret()
|
||||
// Also known as an 'interprocedural jump'.
|
||||
// Target of jump will eventually return to caller.
|
||||
// TailJump below removes the return address.
|
||||
// Don't use rbp for 'jump_target' because a MachEpilogNode has already been
|
||||
// emitted just above the TailCall which has reset rbp to the caller state.
|
||||
instruct TailCalljmpInd(no_rbp_RegP jump_target, rbx_RegP method_ptr)
|
||||
%{
|
||||
match(TailCall jump_target method_ptr);
|
||||
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @key stress randomness
|
||||
* @bug 8329258
|
||||
* @summary Test correct execution of the tail call at the end of the arraycopy stub.
|
||||
* @requires vm.compiler2.enabled
|
||||
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -Xbatch -XX:-TieredCompilation
|
||||
* -XX:+StressGCM -XX:+StressLCM
|
||||
* -XX:CompileCommand=quiet -XX:CompileCommand=compileonly,*::test
|
||||
* compiler.arraycopy.TestTailCallInArrayCopyStub
|
||||
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -Xbatch -XX:-TieredCompilation
|
||||
* -XX:+StressGCM -XX:+StressLCM -XX:StressSeed=75451718
|
||||
* -XX:CompileCommand=quiet -XX:CompileCommand=compileonly,*::test
|
||||
* compiler.arraycopy.TestTailCallInArrayCopyStub
|
||||
*/
|
||||
|
||||
package compiler.arraycopy;
|
||||
|
||||
public class TestTailCallInArrayCopyStub {
|
||||
|
||||
public static void test(byte[] src, byte[] dst) {
|
||||
try {
|
||||
System.arraycopy(src, -1, dst, 0, src.length);
|
||||
} catch (Exception e) {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
byte[] array = new byte[5];
|
||||
for (int i = 0; i < 10_000; ++i) {
|
||||
test(array, array);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user