Skip to content

Commit

Permalink
8329258: TailCall should not use frame pointer register for jump target
Browse files Browse the repository at this point in the history
Backport-of: cccc953
  • Loading branch information
TheRealMDoerr committed Jun 12, 2024
1 parent 9040078 commit 45d5ae0
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 4 deletions.
28 changes: 26 additions & 2 deletions src/hotspot/cpu/aarch64/aarch64.ad
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -4885,6 +4895,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()
%{
Expand Down Expand Up @@ -16562,7 +16584,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);

Expand All @@ -16575,7 +16599,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);

Expand Down
31 changes: 29 additions & 2 deletions src/hotspot/cpu/riscv/riscv.ad
Original file line number Diff line number Diff line change
Expand Up @@ -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;
%}
Expand All @@ -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
Expand Down Expand Up @@ -1017,6 +1025,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 {

Expand Down Expand Up @@ -1079,6 +1088,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() {

Expand Down Expand Up @@ -1113,6 +1123,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() {
Expand Down Expand Up @@ -3189,6 +3202,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));
Expand Down Expand Up @@ -10241,7 +10266,9 @@ instruct cmpFastUnlock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp1, iR
// 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);

Expand All @@ -10254,7 +10281,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);

Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/cpu/x86/x86_32.ad
Original file line number Diff line number Diff line change
Expand Up @@ -13707,6 +13707,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);
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/cpu/x86/x86_64.ad
Original file line number Diff line number Diff line change
Expand Up @@ -13455,6 +13455,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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
}

0 comments on commit 45d5ae0

Please sign in to comment.