jdk-24/test/hotspot/jtreg/compiler/c2/aarch64/TestFarJump.java
2024-01-09 10:33:52 +00:00

137 lines
5.2 KiB
Java

/*
* Copyright (c) 2024, BELLSOFT. 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
* @bug 8280872
* @summary Far call to runtime stub should be generated with single instruction for CodeHeap 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.TestFarJump
*/
public class TestFarJump {
// ADRP instruction encoding:
// |31 30 29 28|27 26 25 24|23 22 21 20|19 18 17 16|15 14 13 12|11 10 09 08|07 06 05 04|03 02 01 10|
// | 1|immlo| 1 0 0 0 0| immhi | Rd |
static boolean isADRP(int encoding) {
final int mask = 0b1001_1111;
final int val = 0b1001_0000;
return ((encoding >> 24) & mask) == val;
}
// Looking for adrp instruction in binary/text assembly output:
// 0x0000ffff7ff1b7d0: c8ff ffd0 | 0801 1091 | 0001 1fd6
// 0x0000ffff6bf20ee0: adrp x8, 0x0000ffff6bef1000
static boolean containsADRP(String input) {
int index = input.indexOf(": ");
if (index == -1) {
return false;
}
input = input.substring(index + 1);
if (input.contains("adrp")) {
return true;
}
Pattern pattern = Pattern.compile("[0-9a-f ]*");
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
String match = matcher.group();
match = match.replace(" " , "");
if (match.length() != 8) {
continue;
}
int dump = (int)Long.parseLong(match, 16);
int encoding = Integer.reverseBytes(dump);
// Check the first instruction only. The raw pointer can be confused with the encoded adrp instruction:
// emit_exception_handler() = far_call() + should_not_reach_here() = ADRP + ADD + BLR + DCPS1 + raw_pointer
return isADRP(encoding);
}
return false;
}
static void runVM(boolean bigCodeHeap) throws Exception {
String className = TestFarJump.class.getName();
String[] procArgs = {
"-XX:-Inline",
"-Xcomp",
"-Xbatch",
"-XX:+TieredCompilation",
"-XX:+SegmentedCodeCache",
"-XX:ReservedCodeCacheSize=" + (bigCodeHeap ? "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("[Exception Handler]")) {
String next1 = itr.next();
String next2 = itr.next();
System.out.println(line);
System.out.println(next1);
System.out.println(next2);
boolean containsADRP = containsADRP(next1) || containsADRP(next2);
if (bigCodeHeap && !containsADRP) {
throw new RuntimeException("ADRP instruction is expected on far jump");
}
if (!bigCodeHeap && containsADRP) {
throw new RuntimeException("for CodeHeap < 250MB the far jump is expected to be encoded with a single branch instruction");
}
return;
}
}
throw new RuntimeException("Assembly output: exception Handler 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");
}
}
}