mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-09 04:59:33 +00:00
8358329: AArch64: emit direct branches in static stubs for small code caches
Reviewed-by: aph, eastigeevich
This commit is contained in:
parent
547ce03016
commit
ba32b78bfa
@ -90,13 +90,15 @@ void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address
|
||||
= nativeMovConstReg_at(stub + NativeInstruction::instruction_size);
|
||||
|
||||
#ifdef ASSERT
|
||||
NativeGeneralJump* jump = nativeGeneralJump_at(method_holder->next_instruction_address());
|
||||
NativeJump* jump = MacroAssembler::codestub_branch_needs_far_jump()
|
||||
? nativeGeneralJump_at(method_holder->next_instruction_address())
|
||||
: nativeJump_at(method_holder->next_instruction_address());
|
||||
verify_mt_safe(callee, entry, method_holder, jump);
|
||||
#endif
|
||||
|
||||
// Update stub.
|
||||
method_holder->set_data((intptr_t)callee());
|
||||
NativeGeneralJump::insert_unconditional(method_holder->next_instruction_address(), entry);
|
||||
MacroAssembler::pd_patch_instruction(method_holder->next_instruction_address(), entry);
|
||||
ICache::invalidate_range(stub, to_interp_stub_size());
|
||||
// Update jump to call.
|
||||
set_destination_mt_safe(stub);
|
||||
|
||||
@ -984,11 +984,19 @@ void MacroAssembler::emit_static_call_stub() {
|
||||
mov_metadata(rmethod, nullptr);
|
||||
|
||||
// Jump to the entry point of the c2i stub.
|
||||
movptr(rscratch1, 0);
|
||||
br(rscratch1);
|
||||
if (codestub_branch_needs_far_jump()) {
|
||||
movptr(rscratch1, 0);
|
||||
br(rscratch1);
|
||||
} else {
|
||||
b(pc());
|
||||
}
|
||||
}
|
||||
|
||||
int MacroAssembler::static_call_stub_size() {
|
||||
if (!codestub_branch_needs_far_jump()) {
|
||||
// isb; movk; movz; movz; b
|
||||
return 5 * NativeInstruction::instruction_size;
|
||||
}
|
||||
// isb; movk; movz; movz; movk; movz; movz; br
|
||||
return 8 * NativeInstruction::instruction_size;
|
||||
}
|
||||
|
||||
@ -386,18 +386,6 @@ void NativeJump::patch_verified_entry(address entry, address verified_entry, add
|
||||
|
||||
void NativeGeneralJump::verify() { }
|
||||
|
||||
void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
|
||||
NativeGeneralJump* n_jump = (NativeGeneralJump*)code_pos;
|
||||
|
||||
CodeBuffer cb(code_pos, instruction_size);
|
||||
MacroAssembler a(&cb);
|
||||
|
||||
a.movptr(rscratch1, (uintptr_t)entry);
|
||||
a.br(rscratch1);
|
||||
|
||||
ICache::invalidate_range(code_pos, instruction_size);
|
||||
}
|
||||
|
||||
// MT-safe patching of a long jump instruction.
|
||||
void NativeGeneralJump::replace_mt_safe(address instr_addr, address code_buffer) {
|
||||
ShouldNotCallThis();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2108, Red Hat Inc. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2025, Red Hat Inc. 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
|
||||
@ -383,7 +383,6 @@ public:
|
||||
address jump_destination() const;
|
||||
void set_jump_destination(address dest);
|
||||
|
||||
static void insert_unconditional(address code_pos, address entry);
|
||||
static void replace_mt_safe(address instr_addr, address code_buffer);
|
||||
static void verify();
|
||||
};
|
||||
|
||||
144
test/hotspot/jtreg/compiler/c2/aarch64/TestStaticCallStub.java
Normal file
144
test/hotspot/jtreg/compiler/c2/aarch64/TestStaticCallStub.java
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2025, 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.
|
||||
*/
|
||||
package compiler.c2.aarch64;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Calls to c2i interface stubs should be generated with near branches
|
||||
* for segmented code cache up to 250MB
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @requires vm.flagless
|
||||
* @requires os.arch=="aarch64"
|
||||
* @requires vm.debug == false
|
||||
* @requires vm.compiler2.enabled
|
||||
*
|
||||
* @run driver compiler.c2.aarch64.TestStaticCallStub
|
||||
*/
|
||||
public class TestStaticCallStub {
|
||||
|
||||
static String[] nearStaticCallOpcodeSeq = {"isb", "mov", "movk", "movk", "b"};
|
||||
static String[] farStaticCallOpcodeSeq = {"isb", "mov", "movk", "movk", "mov", "movk", "movk", "br"};
|
||||
|
||||
static String extractOpcode(String line) {
|
||||
line = line.trim();
|
||||
int semicolonIndex = line.indexOf(';');
|
||||
if (semicolonIndex != -1) {
|
||||
line = line.substring(0, semicolonIndex).trim();
|
||||
}
|
||||
|
||||
String[] words = line.split("\\s+");
|
||||
if (words.length > 1) {
|
||||
return words[1];
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static List<String> extractOpcodesN(ListIterator<String> itr, int n) {
|
||||
List<String> extractedOpcodes = new ArrayList<>();
|
||||
|
||||
while (itr.hasNext() && extractedOpcodes.size() < n) {
|
||||
String opcode = extractOpcode(itr.next());
|
||||
if (!opcode.isEmpty()) {
|
||||
extractedOpcodes.add(opcode);
|
||||
}
|
||||
}
|
||||
|
||||
return extractedOpcodes;
|
||||
}
|
||||
|
||||
static void verifyNearStaticCall(ListIterator<String> itr) {
|
||||
List<String> extractedOpcodes = extractOpcodesN(itr, nearStaticCallOpcodeSeq.length);
|
||||
|
||||
if (!Arrays.asList(nearStaticCallOpcodeSeq).equals(extractedOpcodes)) {
|
||||
throw new RuntimeException("for code cache < 250MB the static call stub is expected to be implemented using near branch");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void verifyFarStaticCall(ListIterator<String> itr) {
|
||||
List<String> extractedOpcodes = extractOpcodesN(itr, farStaticCallOpcodeSeq.length);
|
||||
|
||||
if (!Arrays.asList(farStaticCallOpcodeSeq).equals(extractedOpcodes)) {
|
||||
throw new RuntimeException("for code cache > 250MB the static call stub is expected to be implemented using far branch");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void runVM(boolean bigCodeCache) throws Exception {
|
||||
String className = TestStaticCallStub.class.getName();
|
||||
String[] procArgs = {
|
||||
"-XX:-Inline",
|
||||
"-Xcomp",
|
||||
"-Xbatch",
|
||||
"-XX:+TieredCompilation",
|
||||
"-XX:+SegmentedCodeCache",
|
||||
"-XX:ReservedCodeCacheSize=" + (bigCodeCache ? "256M" : "200M"),
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:CompileCommand=option," + className + "::main,bool,PrintAssembly,true",
|
||||
className};
|
||||
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(procArgs);
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
List<String> lines = output.asLines();
|
||||
|
||||
ListIterator<String> itr = lines.listIterator();
|
||||
while (itr.hasNext()) {
|
||||
String line = itr.next();
|
||||
if (line.contains("{static_stub}")) {
|
||||
itr.previous();
|
||||
if (bigCodeCache) {
|
||||
verifyFarStaticCall(itr);
|
||||
} else {
|
||||
verifyNearStaticCall(itr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Assembly output: static call stub is not found");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length == 0) {
|
||||
// Main VM: fork VM with options
|
||||
runVM(true);
|
||||
runVM(false);
|
||||
return;
|
||||
}
|
||||
if (args.length > 0) {
|
||||
// We are in a forked VM. Just exit
|
||||
System.out.println("Ok");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user