Skip to content

Commit ba32b78

Browse files
Mikhail AblakatovEvgeny Astigeevich
authored andcommitted
8358329: AArch64: emit direct branches in static stubs for small code caches
Reviewed-by: aph, eastigeevich
1 parent 547ce03 commit ba32b78

File tree

5 files changed

+160
-19
lines changed

5 files changed

+160
-19
lines changed

src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,15 @@ void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address
9090
= nativeMovConstReg_at(stub + NativeInstruction::instruction_size);
9191

9292
#ifdef ASSERT
93-
NativeGeneralJump* jump = nativeGeneralJump_at(method_holder->next_instruction_address());
93+
NativeJump* jump = MacroAssembler::codestub_branch_needs_far_jump()
94+
? nativeGeneralJump_at(method_holder->next_instruction_address())
95+
: nativeJump_at(method_holder->next_instruction_address());
9496
verify_mt_safe(callee, entry, method_holder, jump);
9597
#endif
9698

9799
// Update stub.
98100
method_holder->set_data((intptr_t)callee());
99-
NativeGeneralJump::insert_unconditional(method_holder->next_instruction_address(), entry);
101+
MacroAssembler::pd_patch_instruction(method_holder->next_instruction_address(), entry);
100102
ICache::invalidate_range(stub, to_interp_stub_size());
101103
// Update jump to call.
102104
set_destination_mt_safe(stub);

src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -984,11 +984,19 @@ void MacroAssembler::emit_static_call_stub() {
984984
mov_metadata(rmethod, nullptr);
985985

986986
// Jump to the entry point of the c2i stub.
987-
movptr(rscratch1, 0);
988-
br(rscratch1);
987+
if (codestub_branch_needs_far_jump()) {
988+
movptr(rscratch1, 0);
989+
br(rscratch1);
990+
} else {
991+
b(pc());
992+
}
989993
}
990994

991995
int MacroAssembler::static_call_stub_size() {
996+
if (!codestub_branch_needs_far_jump()) {
997+
// isb; movk; movz; movz; b
998+
return 5 * NativeInstruction::instruction_size;
999+
}
9921000
// isb; movk; movz; movz; movk; movz; movz; br
9931001
return 8 * NativeInstruction::instruction_size;
9941002
}

src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -386,18 +386,6 @@ void NativeJump::patch_verified_entry(address entry, address verified_entry, add
386386

387387
void NativeGeneralJump::verify() { }
388388

389-
void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
390-
NativeGeneralJump* n_jump = (NativeGeneralJump*)code_pos;
391-
392-
CodeBuffer cb(code_pos, instruction_size);
393-
MacroAssembler a(&cb);
394-
395-
a.movptr(rscratch1, (uintptr_t)entry);
396-
a.br(rscratch1);
397-
398-
ICache::invalidate_range(code_pos, instruction_size);
399-
}
400-
401389
// MT-safe patching of a long jump instruction.
402390
void NativeGeneralJump::replace_mt_safe(address instr_addr, address code_buffer) {
403391
ShouldNotCallThis();

src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
3-
* Copyright (c) 2014, 2108, Red Hat Inc. All rights reserved.
2+
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2014, 2025, Red Hat Inc. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
66
* This code is free software; you can redistribute it and/or modify it
@@ -383,7 +383,6 @@ class NativeGeneralJump: public NativeJump {
383383
address jump_destination() const;
384384
void set_jump_destination(address dest);
385385

386-
static void insert_unconditional(address code_pos, address entry);
387386
static void replace_mt_safe(address instr_addr, address code_buffer);
388387
static void verify();
389388
};
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Copyright (c) 2025, Arm Limited. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
package compiler.c2.aarch64;
24+
25+
import jdk.test.lib.process.OutputAnalyzer;
26+
import jdk.test.lib.process.ProcessTools;
27+
import java.util.regex.Matcher;
28+
import java.util.regex.Pattern;
29+
import java.util.*;
30+
31+
/*
32+
* @test
33+
* @summary Calls to c2i interface stubs should be generated with near branches
34+
* for segmented code cache up to 250MB
35+
* @library /test/lib /
36+
*
37+
* @requires vm.flagless
38+
* @requires os.arch=="aarch64"
39+
* @requires vm.debug == false
40+
* @requires vm.compiler2.enabled
41+
*
42+
* @run driver compiler.c2.aarch64.TestStaticCallStub
43+
*/
44+
public class TestStaticCallStub {
45+
46+
static String[] nearStaticCallOpcodeSeq = {"isb", "mov", "movk", "movk", "b"};
47+
static String[] farStaticCallOpcodeSeq = {"isb", "mov", "movk", "movk", "mov", "movk", "movk", "br"};
48+
49+
static String extractOpcode(String line) {
50+
line = line.trim();
51+
int semicolonIndex = line.indexOf(';');
52+
if (semicolonIndex != -1) {
53+
line = line.substring(0, semicolonIndex).trim();
54+
}
55+
56+
String[] words = line.split("\\s+");
57+
if (words.length > 1) {
58+
return words[1];
59+
}
60+
61+
return "";
62+
}
63+
64+
static List<String> extractOpcodesN(ListIterator<String> itr, int n) {
65+
List<String> extractedOpcodes = new ArrayList<>();
66+
67+
while (itr.hasNext() && extractedOpcodes.size() < n) {
68+
String opcode = extractOpcode(itr.next());
69+
if (!opcode.isEmpty()) {
70+
extractedOpcodes.add(opcode);
71+
}
72+
}
73+
74+
return extractedOpcodes;
75+
}
76+
77+
static void verifyNearStaticCall(ListIterator<String> itr) {
78+
List<String> extractedOpcodes = extractOpcodesN(itr, nearStaticCallOpcodeSeq.length);
79+
80+
if (!Arrays.asList(nearStaticCallOpcodeSeq).equals(extractedOpcodes)) {
81+
throw new RuntimeException("for code cache < 250MB the static call stub is expected to be implemented using near branch");
82+
}
83+
84+
return;
85+
}
86+
87+
static void verifyFarStaticCall(ListIterator<String> itr) {
88+
List<String> extractedOpcodes = extractOpcodesN(itr, farStaticCallOpcodeSeq.length);
89+
90+
if (!Arrays.asList(farStaticCallOpcodeSeq).equals(extractedOpcodes)) {
91+
throw new RuntimeException("for code cache > 250MB the static call stub is expected to be implemented using far branch");
92+
}
93+
94+
return;
95+
}
96+
97+
static void runVM(boolean bigCodeCache) throws Exception {
98+
String className = TestStaticCallStub.class.getName();
99+
String[] procArgs = {
100+
"-XX:-Inline",
101+
"-Xcomp",
102+
"-Xbatch",
103+
"-XX:+TieredCompilation",
104+
"-XX:+SegmentedCodeCache",
105+
"-XX:ReservedCodeCacheSize=" + (bigCodeCache ? "256M" : "200M"),
106+
"-XX:+UnlockDiagnosticVMOptions",
107+
"-XX:CompileCommand=option," + className + "::main,bool,PrintAssembly,true",
108+
className};
109+
110+
111+
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(procArgs);
112+
OutputAnalyzer output = new OutputAnalyzer(pb.start());
113+
List<String> lines = output.asLines();
114+
115+
ListIterator<String> itr = lines.listIterator();
116+
while (itr.hasNext()) {
117+
String line = itr.next();
118+
if (line.contains("{static_stub}")) {
119+
itr.previous();
120+
if (bigCodeCache) {
121+
verifyFarStaticCall(itr);
122+
} else {
123+
verifyNearStaticCall(itr);
124+
}
125+
return;
126+
}
127+
}
128+
throw new RuntimeException("Assembly output: static call stub is not found");
129+
}
130+
131+
public static void main(String[] args) throws Exception {
132+
if (args.length == 0) {
133+
// Main VM: fork VM with options
134+
runVM(true);
135+
runVM(false);
136+
return;
137+
}
138+
if (args.length > 0) {
139+
// We are in a forked VM. Just exit
140+
System.out.println("Ok");
141+
}
142+
}
143+
}
144+

0 commit comments

Comments
 (0)