8218074: Update Graal
Reviewed-by: kvn
This commit is contained in:
parent
ebcf4ca1e7
commit
c7219faf86
@ -461,6 +461,7 @@ jdk.internal.vm.compiler_EXCLUDES += \
|
||||
org.graalvm.compiler.debug.test \
|
||||
org.graalvm.compiler.graph.test \
|
||||
org.graalvm.compiler.hotspot.amd64.test \
|
||||
org.graalvm.compiler.hotspot.jdk9.test \
|
||||
org.graalvm.compiler.hotspot.lir.test \
|
||||
org.graalvm.compiler.hotspot.sparc.test \
|
||||
org.graalvm.compiler.hotspot.test \
|
||||
|
@ -92,6 +92,7 @@ ifeq ($(INCLUDE_GRAAL), true)
|
||||
$(SRC_DIR)/org.graalvm.compiler.debug.test/src \
|
||||
$(SRC_DIR)/org.graalvm.compiler.graph.test/src \
|
||||
$(SRC_DIR)/org.graalvm.compiler.hotspot.amd64.test/src \
|
||||
$(SRC_DIR)/org.graalvm.compiler.hotspot.jdk9.test/src \
|
||||
$(SRC_DIR)/org.graalvm.compiler.hotspot.lir.test/src \
|
||||
$(SRC_DIR)/org.graalvm.compiler.hotspot.sparc.test/src \
|
||||
$(SRC_DIR)/org.graalvm.compiler.hotspot.test/src \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2019, 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
|
||||
@ -29,6 +29,10 @@ import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
final class Linker {
|
||||
@ -46,9 +50,12 @@ final class Linker {
|
||||
return libraryFileName;
|
||||
}
|
||||
|
||||
private static Stream<String> getLines(InputStream stream) {
|
||||
return new BufferedReader(new InputStreamReader(stream)).lines();
|
||||
}
|
||||
|
||||
private static String getString(InputStream stream) {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(stream));
|
||||
Stream<String> lines = br.lines();
|
||||
Stream<String> lines = getLines(stream);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
lines.iterator().forEachRemaining(e -> sb.append(e));
|
||||
return sb.toString();
|
||||
@ -150,9 +157,18 @@ final class Linker {
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for Visual Studio link.exe Search Order is: VS2013, VS2015, VS2012.
|
||||
* Search for Visual Studio link.exe Search Order is: VS2017+, VS2013, VS2015, VS2012.
|
||||
*/
|
||||
private static String getWindowsLinkPath() {
|
||||
private static String getWindowsLinkPath() throws Exception {
|
||||
try {
|
||||
Path vc141NewerLinker = getVC141AndNewerLinker();
|
||||
if (vc141NewerLinker != null) {
|
||||
return vc141NewerLinker.toString();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
String link = "\\VC\\bin\\amd64\\link.exe";
|
||||
|
||||
/**
|
||||
@ -183,10 +199,46 @@ final class Linker {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Path getVC141AndNewerLinker() throws Exception {
|
||||
String programFilesX86 = System.getenv("ProgramFiles(x86)");
|
||||
if (programFilesX86 == null) {
|
||||
throw new InternalError("Could not read the ProgramFiles(x86) environment variable");
|
||||
}
|
||||
Path vswhere = Paths.get(programFilesX86 + "\\Microsoft Visual Studio\\Installer\\vswhere.exe");
|
||||
if (!Files.exists(vswhere)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(vswhere.toString(), "-requires",
|
||||
"Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "-property", "installationPath", "-latest");
|
||||
processBuilder.redirectOutput(ProcessBuilder.Redirect.PIPE);
|
||||
processBuilder.redirectError(ProcessBuilder.Redirect.PIPE);
|
||||
Process process = processBuilder.start();
|
||||
final int exitCode = process.waitFor();
|
||||
if (exitCode != 0) {
|
||||
String errorMessage = getString(process.getErrorStream());
|
||||
if (errorMessage.isEmpty()) {
|
||||
errorMessage = getString(process.getInputStream());
|
||||
}
|
||||
throw new InternalError(errorMessage);
|
||||
}
|
||||
|
||||
String installationPath = getLines(process.getInputStream()).findFirst().orElseThrow(() -> new InternalError("Unexpected empty output from vswhere"));
|
||||
Path vcToolsVersionFilePath = Paths.get(installationPath, "VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt");
|
||||
List<String> vcToolsVersionFileLines = Files.readAllLines(vcToolsVersionFilePath);
|
||||
if (vcToolsVersionFileLines.isEmpty()) {
|
||||
throw new InternalError(vcToolsVersionFilePath.toString() + " is empty");
|
||||
}
|
||||
String vcToolsVersion = vcToolsVersionFileLines.get(0);
|
||||
Path linkPath = Paths.get(installationPath, "VC\\Tools\\MSVC", vcToolsVersion, "bin\\Hostx64\\x64\\link.exe");
|
||||
if (!Files.exists(linkPath)) {
|
||||
throw new InternalError("Linker at path " + linkPath.toString() + " does not exist");
|
||||
}
|
||||
|
||||
return linkPath;
|
||||
}
|
||||
|
||||
// @formatter:off (workaround for Eclipse formatting bug)
|
||||
/**
|
||||
* Visual Studio supported versions Search Order is: VS2013, VS2015, VS2012.
|
||||
*/
|
||||
enum VSVERSIONS {
|
||||
VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"),
|
||||
VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"),
|
||||
|
@ -166,7 +166,7 @@ public final class Main {
|
||||
printer.printInfo(classesToCompile.size() + " classes found");
|
||||
}
|
||||
|
||||
OptionValues graalOptions = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
|
||||
OptionValues graalOptions = HotSpotGraalOptionValues.defaultOptions();
|
||||
// Setting -Dgraal.TieredAOT overrides --compile-for-tiered
|
||||
if (!TieredAOT.hasBeenSet(graalOptions)) {
|
||||
graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2019, 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
|
||||
@ -30,6 +30,7 @@ import jdk.tools.jaotc.LoadedClass;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.io.File;
|
||||
|
||||
public final class ClassSearch {
|
||||
private final List<SourceProvider> providers = new ArrayList<>();
|
||||
@ -106,7 +107,7 @@ public final class ClassSearch {
|
||||
|
||||
public static List<SearchFor> makeList(String type, String argument) {
|
||||
List<SearchFor> list = new ArrayList<>();
|
||||
String[] elements = argument.split(":");
|
||||
String[] elements = argument.split(File.pathSeparator);
|
||||
for (String element : elements) {
|
||||
list.add(new SearchFor(element, type));
|
||||
}
|
||||
|
@ -880,15 +880,15 @@ public abstract class AArch64Assembler extends Assembler {
|
||||
protected void tbnz(Register reg, int uimm6, int imm16, int pos) {
|
||||
assert reg.getRegisterCategory().equals(CPU);
|
||||
assert NumUtil.isUnsignedNbit(6, uimm6);
|
||||
assert NumUtil.isSignedNbit(18, imm16);
|
||||
assert (imm16 & 3) == 0;
|
||||
assert NumUtil.isSignedNbit(16, imm16) : String.format("Offset value must fit in 16 bits signed: 0x%x", imm16);
|
||||
assert (imm16 & 3) == 0 : String.format("Lower two bits must be zero: 0x%x", imm16 & 3);
|
||||
// size bit is overloaded as top bit of uimm6 bit index
|
||||
int size = (((uimm6 >> 5) & 1) == 0 ? 32 : 64);
|
||||
// remaining 5 bits are encoded lower down
|
||||
int uimm5 = uimm6 >> 1;
|
||||
int offset = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2;
|
||||
int uimm5 = uimm6 & 0x1F;
|
||||
int imm14 = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2;
|
||||
InstructionType type = generalFromSize(size);
|
||||
int encoding = type.encoding | TBNZ.encoding | (uimm5 << 19) | (offset << 5) | rd(reg);
|
||||
int encoding = type.encoding | TBNZ.encoding | (uimm5 << 19) | (imm14 << 5) | rd(reg);
|
||||
if (pos == -1) {
|
||||
emitInt(encoding);
|
||||
} else {
|
||||
@ -907,15 +907,15 @@ public abstract class AArch64Assembler extends Assembler {
|
||||
protected void tbz(Register reg, int uimm6, int imm16, int pos) {
|
||||
assert reg.getRegisterCategory().equals(CPU);
|
||||
assert NumUtil.isUnsignedNbit(6, uimm6);
|
||||
assert NumUtil.isSignedNbit(18, imm16);
|
||||
assert (imm16 & 3) == 0;
|
||||
assert NumUtil.isSignedNbit(16, imm16) : String.format("Offset value must fit in 16 bits signed: 0x%x", imm16);
|
||||
assert (imm16 & 3) == 0 : String.format("Lower two bits must be zero: 0x%x", imm16 & 3);
|
||||
// size bit is overloaded as top bit of uimm6 bit index
|
||||
int size = (((uimm6 >> 5) & 1) == 0 ? 32 : 64);
|
||||
// remaining 5 bits are encoded lower down
|
||||
int uimm5 = uimm6 >> 1;
|
||||
int offset = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2;
|
||||
int uimm5 = uimm6 & 0x1F;
|
||||
int imm14 = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2;
|
||||
InstructionType type = generalFromSize(size);
|
||||
int encoding = type.encoding | TBZ.encoding | (uimm5 << 19) | (offset << 5) | rd(reg);
|
||||
int encoding = type.encoding | TBZ.encoding | (uimm5 << 19) | (imm14 << 5) | rd(reg);
|
||||
if (pos == -1) {
|
||||
emitInt(encoding);
|
||||
} else {
|
||||
|
@ -33,6 +33,9 @@ import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.REG
|
||||
import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.ADD_TO_BASE;
|
||||
import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.ADD_TO_INDEX;
|
||||
import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.NO_WORK;
|
||||
|
||||
import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException;
|
||||
|
||||
import static jdk.vm.ci.aarch64.AArch64.CPU;
|
||||
import static jdk.vm.ci.aarch64.AArch64.r8;
|
||||
import static jdk.vm.ci.aarch64.AArch64.r9;
|
||||
@ -1452,7 +1455,7 @@ public class AArch64MacroAssembler extends AArch64Assembler {
|
||||
*
|
||||
* @param cmp general purpose register. May not be null, zero-register or stackpointer.
|
||||
* @param uimm6 Unsigned 6-bit bit index.
|
||||
* @param label Can only handle 21-bit word-aligned offsets for now. May be unbound. Non null.
|
||||
* @param label Can only handle 16-bit word-aligned offsets for now. May be unbound. Non null.
|
||||
*/
|
||||
public void tbnz(Register cmp, int uimm6, Label label) {
|
||||
assert NumUtil.isUnsignedNbit(6, uimm6);
|
||||
@ -1472,7 +1475,7 @@ public class AArch64MacroAssembler extends AArch64Assembler {
|
||||
*
|
||||
* @param cmp general purpose register. May not be null, zero-register or stackpointer.
|
||||
* @param uimm6 Unsigned 6-bit bit index.
|
||||
* @param label Can only handle 21-bit word-aligned offsets for now. May be unbound. Non null.
|
||||
* @param label Can only handle 16-bit word-aligned offsets for now. May be unbound. Non null.
|
||||
*/
|
||||
public void tbz(Register cmp, int uimm6, Label label) {
|
||||
assert NumUtil.isUnsignedNbit(6, uimm6);
|
||||
@ -1681,6 +1684,9 @@ public class AArch64MacroAssembler extends AArch64Assembler {
|
||||
int sizeEncoding = information & NumUtil.getNbitNumberInt(6);
|
||||
int regEncoding = information >>> 6;
|
||||
Register reg = AArch64.cpuRegisters.get(regEncoding);
|
||||
if (!NumUtil.isSignedNbit(16, branchOffset)) {
|
||||
throw new BranchTargetOutOfBoundsException(true, "Branch target %d out of bounds", branchOffset);
|
||||
}
|
||||
switch (type) {
|
||||
case BRANCH_BIT_NONZERO:
|
||||
super.tbnz(reg, sizeEncoding, branchOffset, branch);
|
||||
|
@ -683,7 +683,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
emitImmediate(asm, size, imm);
|
||||
int nextInsnPos = asm.position();
|
||||
if (annotateImm && asm.codePatchingAnnotationConsumer != null) {
|
||||
asm.codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
|
||||
asm.codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
|
||||
}
|
||||
}
|
||||
|
||||
@ -700,7 +700,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
emitImmediate(asm, size, imm);
|
||||
int nextInsnPos = asm.position();
|
||||
if (annotateImm && asm.codePatchingAnnotationConsumer != null) {
|
||||
asm.codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
|
||||
asm.codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2023,7 +2023,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
emitInt(imm32);
|
||||
int nextInsnPos = position();
|
||||
if (annotateImm && codePatchingAnnotationConsumer != null) {
|
||||
codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
|
||||
codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2201,10 +2201,11 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
}
|
||||
|
||||
public final void movswl(Register dst, AMD64Address src) {
|
||||
prefix(src, dst);
|
||||
emitByte(0x0F);
|
||||
emitByte(0xBF);
|
||||
emitOperandHelper(dst, src, 0);
|
||||
AMD64RMOp.MOVSX.emit(this, DWORD, dst, src);
|
||||
}
|
||||
|
||||
public final void movswq(Register dst, AMD64Address src) {
|
||||
AMD64RMOp.MOVSX.emit(this, QWORD, dst, src);
|
||||
}
|
||||
|
||||
public final void movw(AMD64Address dst, int imm16) {
|
||||
@ -2222,6 +2223,13 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
emitOperandHelper(src, dst, 0);
|
||||
}
|
||||
|
||||
public final void movw(Register dst, AMD64Address src) {
|
||||
emitByte(0x66);
|
||||
prefix(src, dst);
|
||||
emitByte(0x8B);
|
||||
emitOperandHelper(dst, src, 0);
|
||||
}
|
||||
|
||||
public final void movzbl(Register dst, AMD64Address src) {
|
||||
prefix(src, dst);
|
||||
emitByte(0x0F);
|
||||
@ -2237,11 +2245,16 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
AMD64RMOp.MOVZXB.emit(this, QWORD, dst, src);
|
||||
}
|
||||
|
||||
public final void movzbq(Register dst, AMD64Address src) {
|
||||
AMD64RMOp.MOVZXB.emit(this, QWORD, dst, src);
|
||||
}
|
||||
|
||||
public final void movzwl(Register dst, AMD64Address src) {
|
||||
prefix(src, dst);
|
||||
emitByte(0x0F);
|
||||
emitByte(0xB7);
|
||||
emitOperandHelper(dst, src, 0);
|
||||
AMD64RMOp.MOVZX.emit(this, DWORD, dst, src);
|
||||
}
|
||||
|
||||
public final void movzwq(Register dst, AMD64Address src) {
|
||||
AMD64RMOp.MOVZX.emit(this, QWORD, dst, src);
|
||||
}
|
||||
|
||||
public final void negl(Register dst) {
|
||||
@ -2557,16 +2570,63 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
emitModRM(dst, src);
|
||||
}
|
||||
|
||||
// Insn: VPMOVZXBW xmm1, xmm2/m64
|
||||
|
||||
public final void pmovzxbw(Register dst, AMD64Address src) {
|
||||
private void pmovSZx(Register dst, AMD64Address src, int op) {
|
||||
assert supports(CPUFeature.SSE4_1);
|
||||
assert inRC(XMM, dst);
|
||||
simdPrefix(dst, Register.None, src, PD, P_0F38, false);
|
||||
emitByte(0x30);
|
||||
emitByte(op);
|
||||
emitOperandHelper(dst, src, 0);
|
||||
}
|
||||
|
||||
public final void pmovsxbw(Register dst, AMD64Address src) {
|
||||
pmovSZx(dst, src, 0x20);
|
||||
}
|
||||
|
||||
public final void pmovsxbd(Register dst, AMD64Address src) {
|
||||
pmovSZx(dst, src, 0x21);
|
||||
}
|
||||
|
||||
public final void pmovsxbq(Register dst, AMD64Address src) {
|
||||
pmovSZx(dst, src, 0x22);
|
||||
}
|
||||
|
||||
public final void pmovsxwd(Register dst, AMD64Address src) {
|
||||
pmovSZx(dst, src, 0x23);
|
||||
}
|
||||
|
||||
public final void pmovsxwq(Register dst, AMD64Address src) {
|
||||
pmovSZx(dst, src, 0x24);
|
||||
}
|
||||
|
||||
public final void pmovsxdq(Register dst, AMD64Address src) {
|
||||
pmovSZx(dst, src, 0x25);
|
||||
}
|
||||
|
||||
// Insn: VPMOVZXBW xmm1, xmm2/m64
|
||||
public final void pmovzxbw(Register dst, AMD64Address src) {
|
||||
pmovSZx(dst, src, 0x30);
|
||||
}
|
||||
|
||||
public final void pmovzxbd(Register dst, AMD64Address src) {
|
||||
pmovSZx(dst, src, 0x31);
|
||||
}
|
||||
|
||||
public final void pmovzxbq(Register dst, AMD64Address src) {
|
||||
pmovSZx(dst, src, 0x32);
|
||||
}
|
||||
|
||||
public final void pmovzxwd(Register dst, AMD64Address src) {
|
||||
pmovSZx(dst, src, 0x33);
|
||||
}
|
||||
|
||||
public final void pmovzxwq(Register dst, AMD64Address src) {
|
||||
pmovSZx(dst, src, 0x34);
|
||||
}
|
||||
|
||||
public final void pmovzxdq(Register dst, AMD64Address src) {
|
||||
pmovSZx(dst, src, 0x35);
|
||||
}
|
||||
|
||||
public final void pmovzxbw(Register dst, Register src) {
|
||||
assert supports(CPUFeature.SSE4_1);
|
||||
assert inRC(XMM, dst) && inRC(XMM, src);
|
||||
@ -2881,6 +2941,10 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
XOR.rmOp.emit(this, DWORD, dst, src);
|
||||
}
|
||||
|
||||
public final void xorq(Register dst, Register src) {
|
||||
XOR.rmOp.emit(this, QWORD, dst, src);
|
||||
}
|
||||
|
||||
public final void xorpd(Register dst, Register src) {
|
||||
SSEOp.XOR.emit(this, PD, dst, src);
|
||||
}
|
||||
@ -3045,7 +3109,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
emitLong(imm64);
|
||||
int nextInsnPos = position();
|
||||
if (annotateImm && codePatchingAnnotationConsumer != null) {
|
||||
codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
|
||||
codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3189,6 +3253,19 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
emitModRM(5, dst);
|
||||
}
|
||||
|
||||
public final void sarq(Register dst, int imm8) {
|
||||
assert isShiftCount(imm8 >> 1) : "illegal shift count";
|
||||
prefixq(dst);
|
||||
if (imm8 == 1) {
|
||||
emitByte(0xD1);
|
||||
emitModRM(7, dst);
|
||||
} else {
|
||||
emitByte(0xC1);
|
||||
emitModRM(7, dst);
|
||||
emitByte(imm8);
|
||||
}
|
||||
}
|
||||
|
||||
public final void sbbq(Register dst, Register src) {
|
||||
SBB.rmOp.emit(this, QWORD, dst, src);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2019, 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
|
||||
@ -210,7 +210,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class OperandDataAnnotation extends CodeAnnotation {
|
||||
public static class OperandDataAnnotation extends CodeAnnotation {
|
||||
/**
|
||||
* The position (bytes from the beginning of the method) of the operand.
|
||||
*/
|
||||
@ -239,30 +239,10 @@ public abstract class AMD64BaseAssembler extends Assembler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Annotation that stores additional information about the displacement of a
|
||||
* {@link Assembler#getPlaceholder placeholder address} that needs patching.
|
||||
*/
|
||||
protected static class AddressDisplacementAnnotation extends OperandDataAnnotation {
|
||||
AddressDisplacementAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) {
|
||||
super(instructionPosition, operandPosition, operandSize, nextInstructionPosition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Annotation that stores additional information about the immediate operand, e.g., of a call
|
||||
* instruction, that needs patching.
|
||||
*/
|
||||
protected static class ImmediateOperandAnnotation extends OperandDataAnnotation {
|
||||
ImmediateOperandAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) {
|
||||
super(instructionPosition, operandPosition, operandSize, nextInstructionPosition);
|
||||
}
|
||||
}
|
||||
|
||||
protected void annotatePatchingImmediate(int operandOffset, int operandSize) {
|
||||
if (codePatchingAnnotationConsumer != null) {
|
||||
int pos = position();
|
||||
codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(pos, pos + operandOffset, operandSize, pos + operandOffset + operandSize));
|
||||
codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(pos, pos + operandOffset, operandSize, pos + operandOffset + operandSize));
|
||||
}
|
||||
}
|
||||
|
||||
@ -581,7 +561,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
|
||||
assert index.equals(Register.None) : "cannot use RIP relative addressing with index register";
|
||||
emitByte(0x05 | regenc);
|
||||
if (codePatchingAnnotationConsumer != null && addr.instructionStartPosition >= 0) {
|
||||
codePatchingAnnotationConsumer.accept(new AddressDisplacementAnnotation(addr.instructionStartPosition, position(), 4, position() + 4 + additionalInstructionSize));
|
||||
codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(addr.instructionStartPosition, position(), 4, position() + 4 + additionalInstructionSize));
|
||||
}
|
||||
emitInt(disp);
|
||||
} else if (base.isValid()) {
|
||||
|
@ -136,9 +136,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.graalvm.compiler.asm.Assembler;
|
||||
import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException;
|
||||
import org.graalvm.compiler.asm.Label;
|
||||
import org.graalvm.compiler.core.common.NumUtil;
|
||||
import org.graalvm.compiler.core.common.PermanentBailoutException;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
|
||||
import jdk.vm.ci.code.Register;
|
||||
@ -1281,7 +1281,7 @@ public abstract class SPARCAssembler extends Assembler {
|
||||
public int setDisp(int inst, int d) {
|
||||
assert this.match(inst);
|
||||
if (!isValidDisp(d)) {
|
||||
throw new PermanentBailoutException("Too large displacement 0x%x in field %s in instruction %s", d, this.disp, this);
|
||||
throw new BranchTargetOutOfBoundsException(true, "Too large displacement 0x%x in field %s in instruction %s", d, this.disp, this);
|
||||
}
|
||||
return this.disp.setBits(inst, d);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import org.graalvm.compiler.api.test.Graal;
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.code.DisassemblerProvider;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.core.gen.LIRGenerationProvider;
|
||||
import org.graalvm.compiler.core.target.Backend;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
@ -90,7 +91,7 @@ public abstract class AssemblerTest extends GraalTest {
|
||||
RegisterConfig registerConfig = codeCache.getRegisterConfig();
|
||||
CompilationIdentifier compilationId = backend.getCompilationIdentifier(method);
|
||||
StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).compilationId(compilationId).build();
|
||||
CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, graph, null).getCallingConvention();
|
||||
CallingConvention cc = ((LIRGenerationProvider) backend).newLIRGenerationResult(compilationId, null, null, graph, null).getCallingConvention();
|
||||
|
||||
CompilationResult compResult = new CompilationResult(graph.compilationId());
|
||||
byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc);
|
||||
|
@ -22,41 +22,23 @@
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.java;
|
||||
package org.graalvm.compiler.asm;
|
||||
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
|
||||
import org.graalvm.compiler.core.common.GraalBailoutException;
|
||||
|
||||
public final class IntegerExactOpSpeculation implements SpeculationReason {
|
||||
@SuppressWarnings("serial")
|
||||
public class BranchTargetOutOfBoundsException extends GraalBailoutException {
|
||||
|
||||
public enum IntegerExactOp {
|
||||
INTEGER_ADD_EXACT,
|
||||
INTEGER_INCREMENT_EXACT,
|
||||
INTEGER_SUBTRACT_EXACT,
|
||||
INTEGER_DECREMENT_EXACT,
|
||||
INTEGER_MULTIPLY_EXACT
|
||||
public BranchTargetOutOfBoundsException(boolean permanent, String format, Object... args) {
|
||||
super(permanent, format, args);
|
||||
}
|
||||
|
||||
protected final String methodDescriptor;
|
||||
protected final IntegerExactOp op;
|
||||
|
||||
public IntegerExactOpSpeculation(ResolvedJavaMethod method, IntegerExactOp op) {
|
||||
this.methodDescriptor = method.format("%H.%n(%p)%R");
|
||||
this.op = op;
|
||||
public BranchTargetOutOfBoundsException(String format, Object... args) {
|
||||
super(format, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return methodDescriptor.hashCode() * 31 + op.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof IntegerExactOpSpeculation) {
|
||||
IntegerExactOpSpeculation other = (IntegerExactOpSpeculation) obj;
|
||||
return op.equals(other.op) && methodDescriptor.equals(other.methodDescriptor);
|
||||
}
|
||||
return false;
|
||||
public BranchTargetOutOfBoundsException(Throwable cause, String format, Object... args) {
|
||||
super(cause, format, args);
|
||||
}
|
||||
|
||||
}
|
@ -55,6 +55,7 @@ import jdk.vm.ci.meta.Assumptions.Assumption;
|
||||
import jdk.vm.ci.meta.InvokeTarget;
|
||||
import jdk.vm.ci.meta.ResolvedJavaField;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.SpeculationLog;
|
||||
|
||||
/**
|
||||
* Represents the output from compiling a method, including the compiled machine code, associated
|
||||
@ -220,6 +221,11 @@ public class CompilationResult {
|
||||
*/
|
||||
private ResolvedJavaMethod[] methods;
|
||||
|
||||
/**
|
||||
* The {@link SpeculationLog} log used during compilation.
|
||||
*/
|
||||
private SpeculationLog speculationLog;
|
||||
|
||||
/**
|
||||
* The list of fields that were accessed from the bytecodes.
|
||||
*/
|
||||
@ -372,6 +378,21 @@ public class CompilationResult {
|
||||
return methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link SpeculationLog} log used during compilation.
|
||||
*/
|
||||
public void setSpeculationLog(SpeculationLog speculationLog) {
|
||||
checkOpen();
|
||||
this.speculationLog = speculationLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link SpeculationLog} log, if any, used during compilation.
|
||||
*/
|
||||
public SpeculationLog getSpeculationLog() {
|
||||
return speculationLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fields that were referenced from the bytecodes that were used as input to the
|
||||
* compilation.
|
||||
@ -615,7 +636,7 @@ public class CompilationResult {
|
||||
/**
|
||||
* @return the code annotations or {@code null} if there are none
|
||||
*/
|
||||
public List<CodeAnnotation> getAnnotations() {
|
||||
public List<CodeAnnotation> getCodeAnnotations() {
|
||||
if (annotations == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@ -706,7 +727,8 @@ public class CompilationResult {
|
||||
* Clears the information in this object pertaining to generating code. That is, the
|
||||
* {@linkplain #getMarks() marks}, {@linkplain #getInfopoints() infopoints},
|
||||
* {@linkplain #getExceptionHandlers() exception handlers}, {@linkplain #getDataPatches() data
|
||||
* patches} and {@linkplain #getAnnotations() annotations} recorded in this object are cleared.
|
||||
* patches} and {@linkplain #getCodeAnnotations() annotations} recorded in this object are
|
||||
* cleared.
|
||||
*/
|
||||
public void resetForEmittingCode() {
|
||||
checkOpen();
|
||||
@ -721,6 +743,14 @@ public class CompilationResult {
|
||||
}
|
||||
}
|
||||
|
||||
public void clearInfopoints() {
|
||||
infopoints.clear();
|
||||
}
|
||||
|
||||
public void clearExceptionHandlers() {
|
||||
exceptionHandlers.clear();
|
||||
}
|
||||
|
||||
private void checkOpen() {
|
||||
if (closed) {
|
||||
throw new IllegalStateException();
|
||||
|
@ -78,7 +78,7 @@ public class HexCodeFileDisassemblerProvider implements DisassemblerProvider {
|
||||
long start = installedCode == null ? 0L : installedCode.getStart();
|
||||
HexCodeFile hcf = new HexCodeFile(code, start, target.arch.getName(), target.wordSize * 8);
|
||||
if (compResult != null) {
|
||||
HexCodeFile.addAnnotations(hcf, compResult.getAnnotations());
|
||||
HexCodeFile.addAnnotations(hcf, compResult.getCodeAnnotations());
|
||||
addExceptionHandlersComment(compResult, hcf);
|
||||
Register fp = regConfig.getFrameRegister();
|
||||
RefMapFormatter slotFormatter = new DefaultRefMapFormatter(target.wordSize, fp, 0);
|
||||
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 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 org.graalvm.compiler.core.aarch64.test;
|
||||
|
||||
import org.graalvm.compiler.lir.LIRInstruction;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class AArch64CbzTest extends AArch64MatchRuleTest {
|
||||
private static final Predicate<LIRInstruction> predicate = op -> (op instanceof AArch64ControlFlow.CompareBranchZeroOp);
|
||||
|
||||
public static int equalsTo(int x) {
|
||||
if (x == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return x - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static int notEqualsTo(int x) {
|
||||
if (x != 0) {
|
||||
return x + 2;
|
||||
} else {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
public static String isNull(String s) {
|
||||
if (s == null) {
|
||||
return "abc";
|
||||
} else {
|
||||
return s + "abc";
|
||||
}
|
||||
}
|
||||
|
||||
public static String isNotNull(String s) {
|
||||
if (s != null) {
|
||||
return s + "abc";
|
||||
} else {
|
||||
return "abc";
|
||||
}
|
||||
}
|
||||
|
||||
public static String objectEqualsNull(String s1, String s2) {
|
||||
if (s1.equals(null)) {
|
||||
return s1 + "abc";
|
||||
} else {
|
||||
return s2 + "abd";
|
||||
}
|
||||
}
|
||||
|
||||
public static String objectEquals(String s1, String s2) {
|
||||
if (s1.equals(s2)) {
|
||||
return s1 + "abc";
|
||||
} else {
|
||||
return s2 + "abd";
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsTo() {
|
||||
test("equalsTo", 0);
|
||||
test("equalsTo", 1);
|
||||
checkLIR("equalsTo", predicate, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotEqualsTo() {
|
||||
test("notEqualsTo", 0);
|
||||
test("notEqualsTo", 1);
|
||||
checkLIR("notEqualsTo", predicate, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsNull() {
|
||||
test("isNull", new Object[]{null});
|
||||
test("isNull", "abc");
|
||||
checkLIR("isNull", predicate, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsNotNull() {
|
||||
test("isNotNull", new Object[]{null});
|
||||
test("isNotNull", "abc");
|
||||
checkLIR("isNotNull", predicate, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectEqualsNull() {
|
||||
test("objectEqualsNull", "ab", "ac");
|
||||
test("objectEqualsNull", "abc", "abc");
|
||||
checkLIR("objectEqualsNull", predicate, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectEquals() {
|
||||
test("objectEquals", "ab", "ac");
|
||||
test("objectEquals", "abc", "abc");
|
||||
checkLIR("objectEquals", predicate, 0);
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 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 org.graalvm.compiler.core.aarch64.test;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.Pair;
|
||||
import org.graalvm.compiler.asm.aarch64.AArch64Assembler.BarrierKind;
|
||||
import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.core.gen.LIRGenerationProvider;
|
||||
import org.graalvm.compiler.core.test.backend.BackendTest;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64Move.MembarOp;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
|
||||
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import jdk.vm.ci.aarch64.AArch64;
|
||||
import jdk.vm.ci.code.MemoryBarriers;
|
||||
import jdk.vm.ci.runtime.JVMCI;
|
||||
import jdk.vm.ci.runtime.JVMCIBackend;
|
||||
|
||||
public class AArch64MembarOpTest extends BackendTest {
|
||||
|
||||
private final JVMCIBackend providers;
|
||||
private final CompilationResultBuilder crb;
|
||||
|
||||
public AArch64MembarOpTest() {
|
||||
this.providers = JVMCI.getRuntime().getHostJVMCIBackend();
|
||||
|
||||
final StructuredGraph graph = parseEager("stub", StructuredGraph.AllowAssumptions.YES);
|
||||
LIRGenerationResult lirGenRes = getLIRGenerationResult(graph);
|
||||
CompilationResult compResult = new CompilationResult(graph.compilationId());
|
||||
this.crb = ((LIRGenerationProvider) getBackend()).newCompilationResultBuilder(lirGenRes, lirGenRes.getFrameMap(), compResult, CompilationResultBuilderFactory.Default);
|
||||
}
|
||||
|
||||
public void stub() {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void checkAArch64() {
|
||||
assumeTrue("skipping AArch64 specific test", JVMCI.getRuntime().getHostJVMCIBackend().getTarget().arch instanceof AArch64);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runNormalMembarTests() {
|
||||
List<Pair<Integer, BarrierKind>> cases = new ArrayList<>();
|
||||
cases.add(Pair.create(MemoryBarriers.LOAD_LOAD, BarrierKind.LOAD_LOAD));
|
||||
cases.add(Pair.create(MemoryBarriers.LOAD_STORE, BarrierKind.LOAD_LOAD));
|
||||
cases.add(Pair.create(MemoryBarriers.LOAD_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.LOAD_LOAD));
|
||||
cases.add(Pair.create(MemoryBarriers.STORE_LOAD, BarrierKind.ANY_ANY));
|
||||
cases.add(Pair.create(MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_LOAD, BarrierKind.ANY_ANY));
|
||||
cases.add(Pair.create(MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY));
|
||||
cases.add(Pair.create(MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY));
|
||||
cases.add(Pair.create(MemoryBarriers.STORE_STORE, BarrierKind.STORE_STORE));
|
||||
cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.LOAD_LOAD, BarrierKind.ANY_ANY));
|
||||
cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY));
|
||||
cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.LOAD_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY));
|
||||
cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.STORE_LOAD, BarrierKind.ANY_ANY));
|
||||
cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_LOAD, BarrierKind.ANY_ANY));
|
||||
cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY));
|
||||
cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_STORE | MemoryBarriers.LOAD_LOAD, BarrierKind.ANY_ANY));
|
||||
|
||||
for (Pair<Integer, BarrierKind> c : cases) {
|
||||
assertArrayEquals(new MembarOpActual(c.getLeft()).emit(new AArch64MacroAssembler(providers.getTarget())),
|
||||
new MembarOpExpected(c.getRight()).emit(new AArch64MacroAssembler(providers.getTarget())));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = AssertionError.class)
|
||||
public void runExceptionalTests() {
|
||||
new MembarOpActual(16).emit(new AArch64MacroAssembler(providers.getTarget()));
|
||||
}
|
||||
|
||||
private class MembarOpActual {
|
||||
private MembarOp op;
|
||||
|
||||
MembarOpActual(int barriers) {
|
||||
op = new MembarOp(barriers);
|
||||
}
|
||||
|
||||
byte[] emit(AArch64MacroAssembler masm) {
|
||||
op.emitCode(crb, masm);
|
||||
return masm.close(false);
|
||||
}
|
||||
}
|
||||
|
||||
private class MembarOpExpected {
|
||||
private BarrierKind barrierKind;
|
||||
|
||||
MembarOpExpected(BarrierKind barrierKind) {
|
||||
this.barrierKind = barrierKind;
|
||||
}
|
||||
|
||||
byte[] emit(AArch64MacroAssembler masm) {
|
||||
masm.dmb(barrierKind);
|
||||
return masm.close(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.core.aarch64.test;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
|
||||
import org.graalvm.compiler.lir.LIR;
|
||||
import org.graalvm.compiler.lir.LIRInstruction;
|
||||
import org.graalvm.compiler.lir.LIRInstructionClass;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
|
||||
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
|
||||
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
|
||||
import org.graalvm.compiler.lir.jtt.LIRTest;
|
||||
import org.graalvm.compiler.lir.jtt.LIRTestSpecification;
|
||||
import org.graalvm.compiler.lir.phases.LIRPhase;
|
||||
import org.graalvm.compiler.lir.phases.LIRSuites;
|
||||
import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import jdk.vm.ci.aarch64.AArch64;
|
||||
import jdk.vm.ci.code.TargetDescription;
|
||||
import jdk.vm.ci.meta.Value;
|
||||
|
||||
public class AArch64TestBitAndBranchTest extends LIRTest {
|
||||
private static final Predicate<LIRInstruction> checkForBitTestAndBranchOp = op -> (op instanceof AArch64ControlFlow.BitTestAndBranchOp);
|
||||
private LIR lir;
|
||||
|
||||
@Before
|
||||
public void checkAArch64() {
|
||||
assumeTrue("skipping AArch64 specific test", getTarget().arch instanceof AArch64);
|
||||
}
|
||||
|
||||
public static long testBit42Snippet(long a, long b, long c) {
|
||||
if ((a & (1 << 42)) == 0) {
|
||||
return b;
|
||||
} else {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBit42() {
|
||||
test("testBit42Snippet", 1L << 42L, Long.MAX_VALUE, Long.MIN_VALUE);
|
||||
test("testBit42Snippet", ~(1L << 42L), Long.MAX_VALUE, Long.MIN_VALUE);
|
||||
checkLIR("testBit42Snippet", checkForBitTestAndBranchOp, 1);
|
||||
}
|
||||
|
||||
private static final LargeOpSpec largeOpSingleNop = new LargeOpSpec((1 << 14 - 2), 2);
|
||||
|
||||
/**
|
||||
* Tests the graceful case, where the estimation for
|
||||
* {@link CompilationResultBuilder#labelWithinRange(LIRInstruction, org.graalvm.compiler.asm.Label, int)}
|
||||
* holds.
|
||||
*/
|
||||
public static int testBitTestAndBranchSingleSnippet(int a) {
|
||||
int res;
|
||||
if (a % 2 == 0) {
|
||||
res = fillOps(largeOpSingleNop, 1);
|
||||
} else {
|
||||
res = fillOps(largeOpSingleNop, 2);
|
||||
}
|
||||
return GraalDirectives.opaque(res);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBitTestAndBranchSingle() {
|
||||
runTest("testBitTestAndBranchSingleSnippet", 1);
|
||||
checkLIR("testBitTestAndBranchSingleSnippet", checkForBitTestAndBranchOp, 1);
|
||||
}
|
||||
|
||||
private static final LargeOpSpec largeOpFourNop = new LargeOpSpec((1 << 14 - 2), 8);
|
||||
|
||||
/**
|
||||
* Tests the case, where the estimation for
|
||||
* {@link CompilationResultBuilder#labelWithinRange(LIRInstruction, org.graalvm.compiler.asm.Label, int)}
|
||||
* does not hold and the code generation must be redone with large branches.
|
||||
*/
|
||||
public static int testBitTestAndBranchFourSnippet(int a) {
|
||||
int res;
|
||||
if (a % 2 == 0) {
|
||||
res = fillOps(largeOpFourNop, 1);
|
||||
} else {
|
||||
res = fillOps(largeOpFourNop, 2);
|
||||
}
|
||||
return GraalDirectives.opaque(res);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBitTestAndBranchFour() {
|
||||
runTest("testBitTestAndBranchFourSnippet", 1);
|
||||
checkLIR("testBitTestAndBranchFourSnippet", checkForBitTestAndBranchOp, 1);
|
||||
}
|
||||
|
||||
private static class LargeOpSpec extends LIRTestSpecification {
|
||||
private final int n;
|
||||
private final int nopCount;
|
||||
|
||||
LargeOpSpec(int n, int nopCount) {
|
||||
super();
|
||||
this.n = n;
|
||||
this.nopCount = nopCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(LIRGeneratorTool gen, Value a) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
gen.append(new NoOp(nopCount));
|
||||
}
|
||||
setResult(a);
|
||||
}
|
||||
}
|
||||
|
||||
public static class NoOp extends AArch64LIRInstruction {
|
||||
private static final LIRInstructionClass<NoOp> TYPE = LIRInstructionClass.create(NoOp.class);
|
||||
private final int nopCount;
|
||||
|
||||
public NoOp(int nopCount) {
|
||||
super(TYPE);
|
||||
this.nopCount = nopCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
|
||||
for (int i = 0; i < nopCount; i++) {
|
||||
masm.nop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@LIRIntrinsic
|
||||
public static int fillOps(@SuppressWarnings("unused") LargeOpSpec s, int a) {
|
||||
return a;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LIRSuites createLIRSuites(OptionValues options) {
|
||||
LIRSuites suites = super.createLIRSuites(options);
|
||||
suites.getPreAllocationOptimizationStage().appendPhase(new CheckPhase());
|
||||
return suites;
|
||||
}
|
||||
|
||||
public class CheckPhase extends LIRPhase<PreAllocationOptimizationContext> {
|
||||
@Override
|
||||
protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreAllocationOptimizationContext context) {
|
||||
lir = lirGenRes.getLIR();
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkLIR(String methodName, Predicate<LIRInstruction> predicate, int expected) {
|
||||
compile(getResolvedJavaMethod(methodName), null);
|
||||
int actualOpNum = 0;
|
||||
for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) {
|
||||
if (predicate.test(ins)) {
|
||||
actualOpNum++;
|
||||
}
|
||||
}
|
||||
Assert.assertEquals(expected, actualOpNum);
|
||||
}
|
||||
}
|
@ -484,26 +484,6 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem
|
||||
getLIRGen().append(new StoreOp(kind, storeAddress, input, state));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value emitMathLog(Value input, boolean base10) {
|
||||
throw GraalError.unimplemented();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value emitMathCos(Value input) {
|
||||
throw GraalError.unimplemented();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value emitMathSin(Value input) {
|
||||
throw GraalError.unimplemented();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value emitMathTan(Value input) {
|
||||
throw GraalError.unimplemented();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitCompareOp(AArch64Kind cmpKind, Variable left, Value right) {
|
||||
throw GraalError.unimplemented();
|
||||
|
@ -52,6 +52,7 @@ import org.graalvm.compiler.lir.aarch64.AArch64ByteSwapOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64Compare;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.BranchOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CompareBranchZeroOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CondMoveOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CondSetOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp;
|
||||
@ -257,6 +258,27 @@ public abstract class AArch64LIRGenerator extends LIRGenerator {
|
||||
@Override
|
||||
public void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
|
||||
double trueDestinationProbability) {
|
||||
if (cond == Condition.EQ) {
|
||||
// emit cbz instruction for IsNullNode.
|
||||
assert !LIRValueUtil.isNullConstant(left) : "emitNullCheckBranch()'s null input should be in right.";
|
||||
if (LIRValueUtil.isNullConstant(right)) {
|
||||
append(new CompareBranchZeroOp(asAllocatable(left), trueDestination, falseDestination, trueDestinationProbability));
|
||||
return;
|
||||
}
|
||||
|
||||
// emit cbz instruction for IntegerEquals when any of the inputs is zero.
|
||||
AArch64Kind kind = (AArch64Kind) cmpKind;
|
||||
if (kind.isInteger()) {
|
||||
if (isIntConstant(left, 0)) {
|
||||
append(new CompareBranchZeroOp(asAllocatable(right), trueDestination, falseDestination, trueDestinationProbability));
|
||||
return;
|
||||
} else if (isIntConstant(right, 0)) {
|
||||
append(new CompareBranchZeroOp(asAllocatable(left), trueDestination, falseDestination, trueDestinationProbability));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean mirrored = emitCompare(cmpKind, left, right, cond, unorderedIsTrue);
|
||||
Condition finalCondition = mirrored ? cond.mirror() : cond;
|
||||
boolean finalUnorderedIsTrue = mirrored ? !unorderedIsTrue : unorderedIsTrue;
|
||||
|
@ -37,11 +37,14 @@ import org.graalvm.compiler.core.match.ComplexMatchResult;
|
||||
import org.graalvm.compiler.core.match.MatchRule;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.lir.LIRFrameState;
|
||||
import org.graalvm.compiler.lir.LabelRef;
|
||||
import org.graalvm.compiler.lir.Variable;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow;
|
||||
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
|
||||
import org.graalvm.compiler.nodes.ConstantNode;
|
||||
import org.graalvm.compiler.nodes.DeoptimizingNode;
|
||||
import org.graalvm.compiler.nodes.IfNode;
|
||||
import org.graalvm.compiler.nodes.NodeView;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.calc.AddNode;
|
||||
@ -178,6 +181,28 @@ public class AArch64NodeMatchRules extends NodeMatchRules {
|
||||
return builder -> getArithmeticLIRGenerator().emitMSub(operand(a), operand(b), operand(c));
|
||||
}
|
||||
|
||||
/**
|
||||
* ((x & (1 << n)) == 0) -> tbz/tbnz n label.
|
||||
*/
|
||||
@MatchRule("(If (IntegerTest value Constant=a))")
|
||||
public ComplexMatchResult testBitAndBranch(IfNode root, ValueNode value, ConstantNode a) {
|
||||
if (value.getStackKind().isNumericInteger()) {
|
||||
long constant = a.asJavaConstant().asLong();
|
||||
if (Long.bitCount(constant) == 1) {
|
||||
int bitToTest = Long.numberOfTrailingZeros(constant);
|
||||
return builder -> {
|
||||
LabelRef trueDestination = getLIRBlock(root.trueSuccessor());
|
||||
LabelRef falseDestination = getLIRBlock(root.falseSuccessor());
|
||||
AllocatableValue src = moveSp(gen.asAllocatable(operand(value)));
|
||||
double trueDestinationProbability = root.getTrueSuccessorProbability();
|
||||
gen.append(new AArch64ControlFlow.BitTestAndBranchOp(trueDestination, falseDestination, src, trueDestinationProbability, bitToTest));
|
||||
return null;
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AArch64LIRGenerator getLIRGeneratorTool() {
|
||||
return (AArch64LIRGenerator) gen;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2019, 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
|
||||
@ -80,13 +80,6 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
|
||||
import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
|
||||
import static org.graalvm.compiler.lir.amd64.AMD64Arithmetic.DREM;
|
||||
import static org.graalvm.compiler.lir.amd64.AMD64Arithmetic.FREM;
|
||||
import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp.BinaryIntrinsicOpcode.POW;
|
||||
import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.COS;
|
||||
import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.EXP;
|
||||
import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.LOG;
|
||||
import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.LOG10;
|
||||
import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.SIN;
|
||||
import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.TAN;
|
||||
|
||||
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
|
||||
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
|
||||
@ -116,8 +109,13 @@ import org.graalvm.compiler.lir.amd64.AMD64ArithmeticLIRGeneratorTool;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64Binary;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ClearRegisterOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64MathCosOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64MathExpOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64MathLog10Op;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64MathLogOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64MathPowOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64MathSinOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64MathTanOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64Move;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64MulDivOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ShiftOp;
|
||||
@ -127,7 +125,6 @@ import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary;
|
||||
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary.AVXBinaryOp;
|
||||
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorUnary;
|
||||
import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator;
|
||||
import org.graalvm.compiler.lir.gen.LIRGenerator;
|
||||
|
||||
import jdk.vm.ci.amd64.AMD64;
|
||||
import jdk.vm.ci.amd64.AMD64.CPUFeature;
|
||||
@ -152,41 +149,11 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
|
||||
|
||||
private static final RegisterValue RCX_I = AMD64.rcx.asValue(LIRKind.value(AMD64Kind.DWORD));
|
||||
|
||||
public AMD64ArithmeticLIRGenerator(AllocatableValue nullRegisterValue, Maths maths) {
|
||||
public AMD64ArithmeticLIRGenerator(AllocatableValue nullRegisterValue) {
|
||||
this.nullRegisterValue = nullRegisterValue;
|
||||
this.maths = maths == null ? new Maths() {
|
||||
} : maths;
|
||||
}
|
||||
|
||||
private final AllocatableValue nullRegisterValue;
|
||||
private final Maths maths;
|
||||
|
||||
/**
|
||||
* Interface for emitting LIR for selected {@link Math} routines. A {@code null} return value
|
||||
* for any method in this interface means the caller must emit the LIR itself.
|
||||
*/
|
||||
public interface Maths {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
default Variable emitLog(LIRGenerator gen, Value input, boolean base10) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
default Variable emitCos(LIRGenerator gen, Value input) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
default Variable emitSin(LIRGenerator gen, Value input) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
default Variable emitTan(LIRGenerator gen, Value input) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variable emitNegate(Value inputVal) {
|
||||
@ -781,6 +748,7 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variable emitRor(Value a, Value b) {
|
||||
switch ((AMD64Kind) a.getPlatformKind()) {
|
||||
case DWORD:
|
||||
@ -1103,65 +1071,36 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
|
||||
|
||||
@Override
|
||||
public Value emitMathLog(Value input, boolean base10) {
|
||||
LIRGenerator gen = getLIRGen();
|
||||
Variable result = maths.emitLog(gen, input, base10);
|
||||
if (result == null) {
|
||||
result = gen.newVariable(LIRKind.combine(input));
|
||||
AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
|
||||
gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), base10 ? LOG10 : LOG, result, asAllocatable(input), stackSlot));
|
||||
if (base10) {
|
||||
return new AMD64MathLog10Op().emitLIRWrapper(getLIRGen(), input);
|
||||
} else {
|
||||
return new AMD64MathLogOp().emitLIRWrapper(getLIRGen(), input);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value emitMathCos(Value input) {
|
||||
LIRGenerator gen = getLIRGen();
|
||||
Variable result = maths.emitCos(gen, input);
|
||||
if (result == null) {
|
||||
result = gen.newVariable(LIRKind.combine(input));
|
||||
AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
|
||||
gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), COS, result, asAllocatable(input), stackSlot));
|
||||
}
|
||||
return result;
|
||||
return new AMD64MathCosOp().emitLIRWrapper(getLIRGen(), input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value emitMathSin(Value input) {
|
||||
LIRGenerator gen = getLIRGen();
|
||||
Variable result = maths.emitSin(gen, input);
|
||||
if (result == null) {
|
||||
result = gen.newVariable(LIRKind.combine(input));
|
||||
AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
|
||||
gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), SIN, result, asAllocatable(input), stackSlot));
|
||||
}
|
||||
return result;
|
||||
return new AMD64MathSinOp().emitLIRWrapper(getLIRGen(), input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value emitMathTan(Value input) {
|
||||
LIRGenerator gen = getLIRGen();
|
||||
Variable result = maths.emitTan(gen, input);
|
||||
if (result == null) {
|
||||
result = gen.newVariable(LIRKind.combine(input));
|
||||
AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
|
||||
gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), TAN, result, asAllocatable(input), stackSlot));
|
||||
}
|
||||
return result;
|
||||
return new AMD64MathTanOp().emitLIRWrapper(getLIRGen(), input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value emitMathExp(Value input) {
|
||||
Variable result = getLIRGen().newVariable(LIRKind.combine(input));
|
||||
AllocatableValue stackSlot = getLIRGen().getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
|
||||
getLIRGen().append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), EXP, result, asAllocatable(input), stackSlot));
|
||||
return result;
|
||||
return new AMD64MathExpOp().emitLIRWrapper(getLIRGen(), input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value emitMathPow(Value input1, Value input2) {
|
||||
Variable result = getLIRGen().newVariable(LIRKind.combine(input1));
|
||||
getLIRGen().append(new AMD64MathIntrinsicBinaryOp(getAMD64LIRGen(), POW, result, asAllocatable(input1), asAllocatable(input2)));
|
||||
return result;
|
||||
public Value emitMathPow(Value x, Value y) {
|
||||
return new AMD64MathPowOp().emitLIRWrapper(getLIRGen(), x, y);
|
||||
}
|
||||
|
||||
protected AMD64LIRGenerator getAMD64LIRGen() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2019, 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
|
||||
@ -41,6 +41,8 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
|
||||
import static org.graalvm.compiler.lir.LIRValueUtil.isIntConstant;
|
||||
import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
|
||||
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
|
||||
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
|
||||
@ -81,6 +83,7 @@ import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatCondSetOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.ReturnOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.StrategySwitchOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.TableSwitchOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.HashTableSwitchOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64LFenceOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64Move;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp;
|
||||
@ -93,6 +96,7 @@ import org.graalvm.compiler.lir.amd64.AMD64ZapRegistersOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ZapStackOp;
|
||||
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
|
||||
import org.graalvm.compiler.lir.gen.LIRGenerator;
|
||||
import org.graalvm.compiler.lir.hashing.Hasher;
|
||||
import org.graalvm.compiler.phases.util.Providers;
|
||||
|
||||
import jdk.vm.ci.amd64.AMD64;
|
||||
@ -545,7 +549,14 @@ public abstract class AMD64LIRGenerator extends LIRGenerator {
|
||||
@Override
|
||||
public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
|
||||
Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
|
||||
append(new AMD64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length), constantLength, directPointers, getMaxVectorSize()));
|
||||
append(new AMD64ArrayEqualsOp(this, kind, kind, result, array1, array2, asAllocatable(length), constantLength, directPointers, getMaxVectorSize()));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variable emitArrayEquals(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
|
||||
Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
|
||||
append(new AMD64ArrayEqualsOp(this, kind1, kind2, result, array1, array2, asAllocatable(length), constantLength, directPointers, getMaxVectorSize()));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -634,6 +645,19 @@ public abstract class AMD64LIRGenerator extends LIRGenerator {
|
||||
append(new TableSwitchOp(lowKey, defaultTarget, targets, key, newVariable(LIRKind.value(target().arch.getWordKind())), newVariable(key.getValueKind())));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<Hasher> hasherFor(JavaConstant[] keyConstants, double minDensity) {
|
||||
return Hasher.forKeys(keyConstants, minDensity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void emitHashTableSwitch(Hasher hasher, JavaConstant[] keys, LabelRef defaultTarget, LabelRef[] targets, Value value) {
|
||||
Value index = hasher.hash(value, arithmeticLIRGen);
|
||||
Variable scratch = newVariable(LIRKind.value(target().arch.getWordKind()));
|
||||
Variable entryScratch = newVariable(LIRKind.value(target().arch.getWordKind()));
|
||||
append(new HashTableSwitchOp(keys, defaultTarget, targets, value, index, scratch, entryScratch));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitPause() {
|
||||
append(new AMD64PauseOp());
|
||||
|
@ -83,8 +83,8 @@ public final class GraalOptions {
|
||||
@Option(help = "", type = OptionType.Debug)
|
||||
public static final OptionKey<String> EscapeAnalyzeOnly = new OptionKey<>(null);
|
||||
|
||||
@Option(help = "", type = OptionType.Expert)
|
||||
public static final OptionKey<Integer> MaximumEscapeAnalysisArrayLength = new OptionKey<>(32);
|
||||
@Option(help = "The maximum length of an array that will be escape analyzed.", type = OptionType.Expert)
|
||||
public static final OptionKey<Integer> MaximumEscapeAnalysisArrayLength = new OptionKey<>(128);
|
||||
|
||||
@Option(help = "", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> PEAInliningHints = new OptionKey<>(false);
|
||||
@ -142,7 +142,7 @@ public final class GraalOptions {
|
||||
public static final OptionKey<Boolean> VerifyPhases = new OptionKey<>(false);
|
||||
|
||||
// Debug settings:
|
||||
@Option(help = "", type = OptionType.Debug)
|
||||
@Option(help = "Start tracing compiled GC barriers after N garbage collections (disabled if N <= 0).", type = OptionType.Debug)
|
||||
public static final OptionKey<Integer> GCDebugStartCycle = new OptionKey<>(-1);
|
||||
|
||||
@Option(help = "Perform platform dependent validation of the Java heap at returns", type = OptionType.Debug)
|
||||
@ -206,9 +206,6 @@ public final class GraalOptions {
|
||||
@Option(help = "Generate position independent code", type = OptionType.Expert)
|
||||
public static final OptionKey<Boolean> GeneratePIC = new OptionKey<>(false);
|
||||
|
||||
@Option(help = "", type = OptionType.Expert)
|
||||
public static final OptionKey<Boolean> CallArrayCopy = new OptionKey<>(true);
|
||||
|
||||
// Runtime settings
|
||||
@Option(help = "", type = OptionType.Expert)
|
||||
public static final OptionKey<Boolean> SupportJsrBytecodes = new OptionKey<>(true);
|
||||
|
@ -37,9 +37,9 @@ public enum SpeculativeExecutionAttacksMitigations {
|
||||
|
||||
public static class Options {
|
||||
// @formatter:off
|
||||
@Option(help = "Select a strategy to mitigate speculative execution attacks (e.g., SPECTRE)", type = OptionType.User)
|
||||
@Option(help = "file:doc-files/MitigateSpeculativeExecutionAttacksHelp.txt")
|
||||
public static final EnumOptionKey<SpeculativeExecutionAttacksMitigations> MitigateSpeculativeExecutionAttacks = new EnumOptionKey<>(None);
|
||||
@Option(help = "Use index masking after bounds check to mitigate speculative execution attacks", type = OptionType.User)
|
||||
@Option(help = "Use index masking after bounds check to mitigate speculative execution attacks.", type = OptionType.User)
|
||||
public static final OptionKey<Boolean> UseIndexMasking = new OptionKey<>(false);
|
||||
// @formatter:on
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
package org.graalvm.compiler.core.common.cfg;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public abstract class AbstractBlockBase<T extends AbstractBlockBase<T>> {
|
||||
|
||||
protected int id;
|
||||
@ -171,4 +173,13 @@ public abstract class AbstractBlockBase<T extends AbstractBlockBase<T>> {
|
||||
public int hashCode() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static class BlockIdComparator implements Comparator<AbstractBlockBase<?>> {
|
||||
@Override
|
||||
public int compare(AbstractBlockBase<?> o1, AbstractBlockBase<?> o2) {
|
||||
return Integer.compare(o1.getId(), o2.getId());
|
||||
}
|
||||
}
|
||||
|
||||
public static final BlockIdComparator BLOCK_ID_COMPARATOR = new BlockIdComparator();
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ public class CFGVerifier {
|
||||
}
|
||||
}
|
||||
|
||||
for (T block : loop.getExits()) {
|
||||
for (T block : loop.getLoopExits()) {
|
||||
assert block.getId() >= loop.getHeader().getId();
|
||||
|
||||
Loop<?> blockLoop = block.getLoop();
|
||||
|
@ -25,19 +25,28 @@
|
||||
|
||||
package org.graalvm.compiler.core.common.cfg;
|
||||
|
||||
import static org.graalvm.compiler.core.common.cfg.AbstractBlockBase.BLOCK_ID_COMPARATOR;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class Loop<T extends AbstractBlockBase<T>> {
|
||||
|
||||
private final Loop<T> parent;
|
||||
private final List<Loop<T>> children;
|
||||
private final ArrayList<Loop<T>> children;
|
||||
|
||||
private final int depth;
|
||||
private final int index;
|
||||
private final T header;
|
||||
private final List<T> blocks;
|
||||
private final List<T> exits;
|
||||
private final ArrayList<T> blocks;
|
||||
private final ArrayList<T> exits;
|
||||
/**
|
||||
* Natural exits, ignoring LoopExitNodes.
|
||||
*
|
||||
* @see #getNaturalExits()
|
||||
*/
|
||||
private final ArrayList<T> naturalExits;
|
||||
|
||||
protected Loop(Loop<T> parent, int index, T header) {
|
||||
this.parent = parent;
|
||||
@ -51,6 +60,7 @@ public abstract class Loop<T extends AbstractBlockBase<T>> {
|
||||
this.blocks = new ArrayList<>();
|
||||
this.children = new ArrayList<>();
|
||||
this.exits = new ArrayList<>();
|
||||
this.naturalExits = new ArrayList<>();
|
||||
}
|
||||
|
||||
public abstract long numBackedges();
|
||||
@ -84,12 +94,87 @@ public abstract class Loop<T extends AbstractBlockBase<T>> {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
public List<T> getExits() {
|
||||
/**
|
||||
* Returns the loop exits.
|
||||
*
|
||||
* This might be a conservative set: before framestate assignment it matches the LoopExitNodes
|
||||
* even if earlier blocks could be considered as exits. After framestate assignments, this is
|
||||
* the same as {@link #getNaturalExits()}.
|
||||
*
|
||||
* <p>
|
||||
* LoopExitNodes are inserted in the control-flow during parsing and are natural exits: they are
|
||||
* the earliest block at which we are guaranteed to have exited the loop. However, after some
|
||||
* transformations of the graph, the natural exit might go up but the LoopExitNodes are not
|
||||
* updated.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* For example in:
|
||||
*
|
||||
* <pre>
|
||||
* for (int i = 0; i < N; i++) {
|
||||
* if (c) {
|
||||
* // Block 1
|
||||
* if (dummy) {
|
||||
* // ...
|
||||
* } else {
|
||||
* // ...
|
||||
* }
|
||||
* if (b) {
|
||||
* continue;
|
||||
* } else {
|
||||
* // Block 2
|
||||
* // LoopExitNode
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* After parsing, the natural exits match the LoopExitNode: Block 2 is a natural exit and has a
|
||||
* LoopExitNode. If the {@code b} condition gets canonicalized to {@code false}, the natural
|
||||
* exit moves to Block 1 while the LoopExitNode remains in Block 2. In such a scenario,
|
||||
* {@code getLoopExits()} will contain block 2 while {@link #getNaturalExits()} will contain
|
||||
* block 1.
|
||||
*
|
||||
*
|
||||
* @see #getNaturalExits()
|
||||
*/
|
||||
public List<T> getLoopExits() {
|
||||
return exits;
|
||||
}
|
||||
|
||||
public void addExit(T t) {
|
||||
exits.add(t);
|
||||
public boolean isLoopExit(T block) {
|
||||
assert isSorted(exits);
|
||||
return Collections.binarySearch(exits, block, BLOCK_ID_COMPARATOR) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the natural exit points: these are the earliest block that are guaranteed to never
|
||||
* reach a back-edge.
|
||||
*
|
||||
* This can not be used in the context of preserving or using loop-closed form.
|
||||
*
|
||||
* @see #getLoopExits()
|
||||
*/
|
||||
public ArrayList<T> getNaturalExits() {
|
||||
return naturalExits;
|
||||
}
|
||||
|
||||
public boolean isNaturalExit(T block) {
|
||||
assert isSorted(naturalExits);
|
||||
return Collections.binarySearch(naturalExits, block, BLOCK_ID_COMPARATOR) >= 0;
|
||||
}
|
||||
|
||||
private static <T extends AbstractBlockBase<T>> boolean isSorted(List<T> list) {
|
||||
int lastId = Integer.MIN_VALUE;
|
||||
for (AbstractBlockBase<?> block : list) {
|
||||
if (block.getId() < lastId) {
|
||||
return false;
|
||||
}
|
||||
lastId = block.getId();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,4 +200,9 @@ public abstract class Loop<T extends AbstractBlockBase<T>> {
|
||||
public int hashCode() {
|
||||
return index + depth * 31;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return super.equals(obj);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
Select a strategy to mitigate speculative execution attacks (e.g., SPECTRE).
|
||||
The accepted values are:
|
||||
None - No mitigations are used in JIT compiled code.
|
||||
AllTargets - All branches are protected against speculative attacks.
|
||||
This has a significant performance impact.
|
||||
GuardTargets - Only branches that preserve Java memory safety are protected.
|
||||
This has less performance impact than AllTargets.
|
||||
NonDeoptGuardTargets - GuardTargets except that branches which deoptimize are not
|
||||
protected since they can not be executed repeatedly.
|
@ -48,6 +48,13 @@ public abstract class AbstractObjectStamp extends AbstractPointerStamp {
|
||||
this.exactType = exactType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Visitor v) {
|
||||
super.accept(v);
|
||||
v.visitObject(type);
|
||||
v.visitBoolean(exactType);
|
||||
}
|
||||
|
||||
protected abstract AbstractObjectStamp copyWith(ResolvedJavaType newType, boolean newExactType, boolean newNonNull, boolean newAlwaysNull);
|
||||
|
||||
@Override
|
||||
|
@ -36,6 +36,12 @@ public abstract class AbstractPointerStamp extends Stamp {
|
||||
private final boolean nonNull;
|
||||
private final boolean alwaysNull;
|
||||
|
||||
@Override
|
||||
public void accept(Visitor v) {
|
||||
v.visitBoolean(nonNull);
|
||||
v.visitBoolean(alwaysNull);
|
||||
}
|
||||
|
||||
protected AbstractPointerStamp(boolean nonNull, boolean alwaysNull) {
|
||||
this.nonNull = nonNull;
|
||||
this.alwaysNull = alwaysNull;
|
||||
|
@ -45,6 +45,10 @@ public final class IllegalStamp extends Stamp {
|
||||
private IllegalStamp() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Visitor v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaKind getStackKind() {
|
||||
return JavaKind.Illegal;
|
||||
|
@ -31,6 +31,7 @@ import jdk.vm.ci.meta.Constant;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.MemoryAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
import jdk.vm.ci.meta.UnresolvedJavaType;
|
||||
|
||||
public class ObjectStamp extends AbstractObjectStamp {
|
||||
|
||||
@ -92,4 +93,48 @@ public class ObjectStamp extends AbstractObjectStamp {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an ObjectStamp into a representation that can be resolved symbolically into the
|
||||
* original stamp.
|
||||
*/
|
||||
@Override
|
||||
public SymbolicJVMCIReference<ObjectStamp> makeSymbolic() {
|
||||
if (type() == null) {
|
||||
return null;
|
||||
}
|
||||
return new SymbolicObjectStamp(this);
|
||||
}
|
||||
|
||||
static class SymbolicObjectStamp implements SymbolicJVMCIReference<ObjectStamp> {
|
||||
UnresolvedJavaType type;
|
||||
private boolean exactType;
|
||||
private boolean nonNull;
|
||||
private boolean alwaysNull;
|
||||
|
||||
SymbolicObjectStamp(ObjectStamp stamp) {
|
||||
if (stamp.type() != null) {
|
||||
type = UnresolvedJavaType.create(stamp.type().getName());
|
||||
}
|
||||
exactType = stamp.isExactType();
|
||||
nonNull = stamp.nonNull();
|
||||
alwaysNull = stamp.alwaysNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectStamp resolve(ResolvedJavaType accessingClass) {
|
||||
return new ObjectStamp(type != null ? type.resolve(accessingClass) : null, exactType, nonNull, alwaysNull);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SymbolicObjectStamp{" +
|
||||
"declaringType=" + type +
|
||||
", exactType=" + exactType +
|
||||
", nonNull=" + nonNull +
|
||||
", alwaysNull=" + alwaysNull +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -39,6 +39,11 @@ public abstract class PrimitiveStamp extends ArithmeticStamp {
|
||||
this.bits = bits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Visitor v) {
|
||||
v.visitInt(bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* The width in bits of the value described by this stamp.
|
||||
*/
|
||||
|
@ -26,6 +26,7 @@ package org.graalvm.compiler.core.common.type;
|
||||
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.core.common.spi.LIRKindTool;
|
||||
import org.graalvm.compiler.serviceprovider.SpeculationReasonGroup.SpeculationContextObject;
|
||||
|
||||
import jdk.vm.ci.meta.Constant;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
@ -36,7 +37,7 @@ import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
/**
|
||||
* A stamp is the basis for a type system.
|
||||
*/
|
||||
public abstract class Stamp {
|
||||
public abstract class Stamp implements SpeculationContextObject {
|
||||
|
||||
protected Stamp() {
|
||||
}
|
||||
@ -185,4 +186,15 @@ public abstract class Stamp {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a Stamp into a representation that can be resolved symbolically into the original
|
||||
* stamp. If this stamp contains no references to JVMCI types then simply return null.
|
||||
*/
|
||||
public SymbolicJVMCIReference<? extends Stamp> makeSymbolic() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract String toString();
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
package org.graalvm.compiler.core.common.type;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A pair of stamp with one being the stamp that can be trusted and the other one being a guess that
|
||||
* needs a dynamic check to be used.
|
||||
@ -63,4 +65,22 @@ public final class StampPair {
|
||||
return trustedStamp + " (unchecked=" + uncheckedStamp + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return trustedStamp.hashCode() + 11 + (uncheckedStamp != null ? uncheckedStamp.hashCode() : 0);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof StampPair) {
|
||||
StampPair other = (StampPair) obj;
|
||||
return trustedStamp.equals(other.trustedStamp) && Objects.equals(uncheckedStamp, other.uncheckedStamp);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.core.common.type;
|
||||
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
|
||||
/**
|
||||
* This interface represents an object which contains a symbolic reference to a JVMCI type or method
|
||||
* that can be converted back into the original object by looking up types relative to an
|
||||
* {@code accessingClass}.
|
||||
*/
|
||||
public interface SymbolicJVMCIReference<T> {
|
||||
T resolve(ResolvedJavaType accessingClass);
|
||||
}
|
@ -42,6 +42,10 @@ public final class VoidStamp extends Stamp {
|
||||
private VoidStamp() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Visitor v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stamp unrestricted() {
|
||||
return this;
|
||||
|
@ -43,6 +43,10 @@ public final class UnsignedLong {
|
||||
return Long.compareUnsigned(value, unsignedValue) < 0;
|
||||
}
|
||||
|
||||
public boolean isGreaterThan(long unsignedValue) {
|
||||
return Long.compareUnsigned(value, unsignedValue) > 0;
|
||||
}
|
||||
|
||||
public boolean isLessOrEqualTo(long unsignedValue) {
|
||||
return Long.compareUnsigned(value, unsignedValue) <= 0;
|
||||
}
|
||||
|
@ -157,6 +157,10 @@ public class CheckGraalInvariants extends GraalCompilerTest {
|
||||
if (className.equals("org.graalvm.compiler.serviceprovider.GraalServices$Lazy")) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (className.equals("jdk.vm.ci.services.JVMCIClassLoaderFactory")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ import org.graalvm.compiler.phases.OptimisticOptimizations;
|
||||
import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization;
|
||||
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
|
||||
import org.graalvm.compiler.phases.common.ConditionalEliminationPhase;
|
||||
import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
|
||||
import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
|
||||
import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
|
||||
import org.graalvm.compiler.phases.common.LoweringPhase;
|
||||
import org.graalvm.compiler.phases.schedule.SchedulePhase;
|
||||
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.iterators.FilteredNodeIterable;
|
||||
import org.graalvm.compiler.loop.LoopEx;
|
||||
import org.graalvm.compiler.loop.LoopsData;
|
||||
import org.graalvm.compiler.nodes.DeoptimizingNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CountedLoopTest2 extends GraalCompilerTest {
|
||||
public static float countedDeoptLoop0(int n) {
|
||||
float v = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
v += 2.1f * i;
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
}
|
||||
GraalDirectives.deoptimizeAndInvalidate();
|
||||
return v;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test0() {
|
||||
test("countedDeoptLoop0");
|
||||
}
|
||||
|
||||
public static float countedDeoptLoop1(int n) {
|
||||
float v = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
v += 2.1f * i;
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
}
|
||||
if (v > 0) {
|
||||
if (v / 55 < 3) {
|
||||
v -= 2;
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
} else {
|
||||
v += 6;
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
}
|
||||
} else {
|
||||
v += 1;
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
}
|
||||
GraalDirectives.deoptimizeAndInvalidate();
|
||||
return v;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test1() {
|
||||
test("countedDeoptLoop1");
|
||||
}
|
||||
|
||||
public static float countedDeoptLoop2(int n, float init) {
|
||||
float v = init;
|
||||
if (v > 0) {
|
||||
if (v / 55 < 3) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
v += 2.1f * i;
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < n; i++) {
|
||||
v += 1.1f * i;
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < n; i++) {
|
||||
v += -0.1f * i;
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
}
|
||||
}
|
||||
GraalDirectives.deoptimizeAndInvalidate();
|
||||
return v;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
test("countedDeoptLoop2", 3);
|
||||
}
|
||||
|
||||
private void test(String methodName) {
|
||||
test(methodName, 1);
|
||||
}
|
||||
|
||||
private void test(String methodName, int nLoops) {
|
||||
StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES);
|
||||
LoopsData loops = new LoopsData(graph);
|
||||
Assert.assertEquals(nLoops, loops.loops().size());
|
||||
for (LoopEx loop : loops.loops()) {
|
||||
Assert.assertTrue(loop.detectCounted());
|
||||
}
|
||||
|
||||
StructuredGraph finalGraph = getFinalGraph(methodName);
|
||||
loops = new LoopsData(finalGraph);
|
||||
Assert.assertEquals(nLoops, loops.loops().size());
|
||||
FilteredNodeIterable<Node> nonStartDeopts = finalGraph.getNodes().filter(n -> {
|
||||
return n instanceof DeoptimizingNode.DeoptBefore && ((DeoptimizingNode.DeoptBefore) n).stateBefore().bci > 0;
|
||||
});
|
||||
Assert.assertTrue(nonStartDeopts.isNotEmpty());
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ import java.nio.file.Path;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import org.graalvm.compiler.debug.DebugOptions;
|
||||
import org.graalvm.compiler.debug.DebugOptions.PrintGraphTarget;
|
||||
import org.graalvm.compiler.options.OptionKey;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.junit.Test;
|
||||
@ -52,7 +53,7 @@ public class DumpPathTest extends GraalCompilerTest {
|
||||
String[] extensions = new String[]{".cfg", ".bgv", ".graph-strings"};
|
||||
EconomicMap<OptionKey<?>, Object> overrides = OptionValues.newOptionMap();
|
||||
overrides.put(DebugOptions.DumpPath, dumpDirectoryPath.toString());
|
||||
overrides.put(DebugOptions.PrintGraphFile, true);
|
||||
overrides.put(DebugOptions.PrintGraph, PrintGraphTarget.File);
|
||||
overrides.put(DebugOptions.PrintCanonicalGraphStrings, true);
|
||||
overrides.put(DebugOptions.Dump, "*");
|
||||
|
||||
|
@ -111,7 +111,7 @@ import org.graalvm.compiler.phases.OptimisticOptimizations;
|
||||
import org.graalvm.compiler.phases.Phase;
|
||||
import org.graalvm.compiler.phases.PhaseSuite;
|
||||
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
|
||||
import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
|
||||
import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
|
||||
import org.graalvm.compiler.phases.common.inlining.InliningPhase;
|
||||
import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
|
||||
import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy;
|
||||
@ -899,11 +899,21 @@ public abstract class GraalCompilerTest extends GraalTest {
|
||||
return actual;
|
||||
}
|
||||
|
||||
private static final List<Class<?>> C2_OMIT_STACK_TRACE_IN_FAST_THROW_EXCEPTIONS = Arrays.asList(
|
||||
ArithmeticException.class,
|
||||
ArrayIndexOutOfBoundsException.class,
|
||||
ArrayStoreException.class,
|
||||
ClassCastException.class,
|
||||
NullPointerException.class);
|
||||
|
||||
protected void assertEquals(Result expect, Result actual) {
|
||||
if (expect.exception != null) {
|
||||
Assert.assertTrue("expected " + expect.exception, actual.exception != null);
|
||||
Assert.assertEquals("Exception class", expect.exception.getClass(), actual.exception.getClass());
|
||||
Assert.assertEquals("Exception message", expect.exception.getMessage(), actual.exception.getMessage());
|
||||
// C2 can optimize out the stack trace and message in some cases
|
||||
if (expect.exception.getMessage() != null || !C2_OMIT_STACK_TRACE_IN_FAST_THROW_EXCEPTIONS.contains(expect.exception.getClass())) {
|
||||
Assert.assertEquals("Exception message", expect.exception.getMessage(), actual.exception.getMessage());
|
||||
}
|
||||
} else {
|
||||
if (actual.exception != null) {
|
||||
throw new AssertionError("expected " + expect.returnValue + " but got an exception", actual.exception);
|
||||
|
@ -30,16 +30,15 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.nodes.EncodedGraph;
|
||||
import org.graalvm.compiler.nodes.GraphEncoder;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
|
||||
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
|
||||
import org.graalvm.compiler.phases.tiers.PhaseContext;
|
||||
import org.junit.Test;
|
||||
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
public class GraphEncoderTest extends GraalCompilerTest {
|
||||
|
||||
@ -80,7 +79,7 @@ public class GraphEncoderTest extends GraalCompilerTest {
|
||||
|
||||
for (StructuredGraph originalGraph : originalGraphs) {
|
||||
EncodedGraph encodedGraph = new EncodedGraph(encoder.getEncoding(), startOffsets.get(originalGraph), encoder.getObjects(), encoder.getNodeClasses(), originalGraph);
|
||||
GraphEncoder.verifyEncoding(originalGraph, encodedGraph, getTarget().arch);
|
||||
encoder.verifyEncoding(originalGraph, encodedGraph);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import java.util.Iterator;
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.graalvm.compiler.core.common.GraalOptions;
|
||||
import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||
import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
|
||||
import org.graalvm.compiler.nodes.GuardNode;
|
||||
import org.graalvm.compiler.nodes.ParameterNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
@ -42,7 +43,6 @@ import org.graalvm.compiler.nodes.calc.IntegerLowerThanNode;
|
||||
import org.graalvm.compiler.nodes.calc.IsNullNode;
|
||||
import org.graalvm.compiler.nodes.spi.LoweringTool;
|
||||
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
|
||||
import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
|
||||
import org.graalvm.compiler.phases.common.FloatingReadPhase;
|
||||
import org.graalvm.compiler.phases.common.LoweringPhase;
|
||||
import org.graalvm.compiler.phases.schedule.SchedulePhase;
|
||||
|
@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, Arm Limited and 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.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class IntegerDivRemConstantTest extends GraalCompilerTest {
|
||||
public static int intDivPositiveConstant(int val) {
|
||||
return val / 5;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntDivPositiveConstant() {
|
||||
test("intDivPositiveConstant", -10);
|
||||
test("intDivPositiveConstant", 0);
|
||||
test("intDivPositiveConstant", 4256);
|
||||
test("intDivPositiveConstant", Integer.MAX_VALUE);
|
||||
test("intDivPositiveConstant", Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static int intDivIntegerMax(int val) {
|
||||
return val / Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntDivIntegerMax() {
|
||||
test("intDivIntegerMax", -10);
|
||||
test("intDivIntegerMax", 0);
|
||||
test("intDivIntegerMax", 4256);
|
||||
test("intDivIntegerMax", Integer.MAX_VALUE);
|
||||
test("intDivIntegerMax", Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static int intDivNegativeConstant(int val) {
|
||||
return val / -1234;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntDivNegativeConstant() {
|
||||
test("intDivNegativeConstant", -123);
|
||||
test("intDivNegativeConstant", 0);
|
||||
test("intDivNegativeConstant", 123);
|
||||
test("intDivNegativeConstant", Integer.MAX_VALUE);
|
||||
test("intDivNegativeConstant", Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static int intDivIntegerMinOdd(int val) {
|
||||
return val / (Integer.MIN_VALUE + 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntDivIntegerMinOdd() {
|
||||
test("intDivIntegerMinOdd", -123);
|
||||
test("intDivIntegerMinOdd", 0);
|
||||
test("intDivIntegerMinOdd", 123);
|
||||
test("intDivIntegerMinOdd", Integer.MAX_VALUE);
|
||||
test("intDivIntegerMinOdd", Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static long longDivPositiveConstant(long val) {
|
||||
return val / 35170432;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongDivPositiveConstant() {
|
||||
test("longDivPositiveConstant", -1234L);
|
||||
test("longDivPositiveConstant", 0L);
|
||||
test("longDivPositiveConstant", 214423L);
|
||||
test("longDivPositiveConstant", Long.MAX_VALUE);
|
||||
test("longDivPositiveConstant", Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static long longDivLongMax(long val) {
|
||||
return val / Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongDivLongMax() {
|
||||
test("longDivLongMax", -1234L);
|
||||
test("longDivLongMax", 0L);
|
||||
test("longDivLongMax", 214423L);
|
||||
test("longDivLongMax", Long.MAX_VALUE);
|
||||
test("longDivLongMax", Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static long longDivNegativeConstant(long val) {
|
||||
return val / -413;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongDivNegativeConstant() {
|
||||
test("longDivNegativeConstant", -43L);
|
||||
test("longDivNegativeConstant", 0L);
|
||||
test("longDivNegativeConstant", 147065L);
|
||||
test("longDivNegativeConstant", Long.MAX_VALUE);
|
||||
test("longDivNegativeConstant", Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static long longDivLongMinOdd(long val) {
|
||||
return val / (Long.MIN_VALUE + 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongDivLongMinOdd() {
|
||||
test("longDivLongMinOdd", -1234L);
|
||||
test("longDivLongMinOdd", 0L);
|
||||
test("longDivLongMinOdd", 214423L);
|
||||
test("longDivLongMinOdd", Long.MAX_VALUE);
|
||||
test("longDivLongMinOdd", Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static int intRemPositiveConstant(int val) {
|
||||
return val % 139968;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntRemPositiveConstant() {
|
||||
test("intRemPositiveConstant", -10);
|
||||
test("intRemPositiveConstant", 0);
|
||||
test("intRemPositiveConstant", 4256);
|
||||
test("intRemPositiveConstant", Integer.MAX_VALUE);
|
||||
test("intRemPositiveConstant", Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static int intRemNegativeConstant(int val) {
|
||||
return val % -139968;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntRemNegativeConstant() {
|
||||
test("intRemNegativeConstant", -10);
|
||||
test("intRemNegativeConstant", 0);
|
||||
test("intRemNegativeConstant", 4256);
|
||||
test("intRemNegativeConstant", Integer.MAX_VALUE);
|
||||
test("intRemNegativeConstant", Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
@SuppressWarnings("divzero")
|
||||
public static int intRemZero(int val) {
|
||||
return val % 0;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntRemZero() {
|
||||
test("intRemZero", -10);
|
||||
test("intRemZero", 0);
|
||||
test("intRemZero", 4256);
|
||||
test("intRemZero", Integer.MAX_VALUE);
|
||||
test("intRemZero", Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static int intRemMax(int val) {
|
||||
return val % Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntRemMax() {
|
||||
test("intRemMax", -10);
|
||||
test("intRemMax", 0);
|
||||
test("intRemMax", 4256);
|
||||
test("intRemMax", Integer.MAX_VALUE);
|
||||
test("intRemMax", Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static int intRemMin(int val) {
|
||||
return val % Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntRemMin() {
|
||||
test("intRemMin", -10);
|
||||
test("intRemMin", 0);
|
||||
test("intRemMin", 4256);
|
||||
test("intRemMin", Integer.MAX_VALUE);
|
||||
test("intRemMin", Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static long longRemPositiveConstant(long val) {
|
||||
return val % 35170432;
|
||||
}
|
||||
|
||||
public static int intRemPowerOf2(int val) {
|
||||
return val % 4;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntRemPowerOf2() {
|
||||
test("intRemPowerOf2", -10);
|
||||
test("intRemPowerOf2", 0);
|
||||
test("intRemPowerOf2", 4256);
|
||||
test("intRemPowerOf2", Integer.MAX_VALUE);
|
||||
test("intRemPowerOf2", Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongRemPositiveConstant() {
|
||||
test("longRemPositiveConstant", -1234L);
|
||||
test("longRemPositiveConstant", 0L);
|
||||
test("longRemPositiveConstant", 214423L);
|
||||
test("longRemPositiveConstant", Long.MAX_VALUE);
|
||||
test("longRemPositiveConstant", Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static long longRemNegativeConstant(long val) {
|
||||
return val % -413;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongRemNegativeConstant() {
|
||||
test("longRemNegativeConstant", -43L);
|
||||
test("longRemNegativeConstant", 0L);
|
||||
test("longRemNegativeConstant", 147065L);
|
||||
test("longRemNegativeConstant", Long.MAX_VALUE);
|
||||
test("longRemNegativeConstant", Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
@SuppressWarnings("divzero")
|
||||
public static long longRemZero(long val) {
|
||||
return val % 0;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongRemZero() {
|
||||
test("longRemZero", -43L);
|
||||
test("longRemZero", 0L);
|
||||
test("longRemZero", 147065L);
|
||||
test("longRemZero", Long.MAX_VALUE);
|
||||
test("longRemZero", Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static long longRemMax(long val) {
|
||||
return val % Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongRemMax() {
|
||||
test("longRemMax", -43L);
|
||||
test("longRemMax", 0L);
|
||||
test("longRemMax", 147065L);
|
||||
test("longRemMax", Long.MAX_VALUE);
|
||||
test("longRemMax", Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static long longRemMin(long val) {
|
||||
return val % Long.MIN_VALUE;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongRemMin() {
|
||||
test("longRemMin", -43L);
|
||||
test("longRemMin", 0L);
|
||||
test("longRemMin", 147065L);
|
||||
test("longRemMin", Long.MAX_VALUE);
|
||||
test("longRemMin", Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
public static long longRemPowerOf2(long val) {
|
||||
return val % 4L;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongRemPowerOf2() {
|
||||
test("longRemPowerOf2", -43L);
|
||||
test("longRemPowerOf2", 0L);
|
||||
test("longRemPowerOf2", 147065L);
|
||||
test("longRemPowerOf2", Long.MAX_VALUE);
|
||||
test("longRemPowerOf2", Long.MIN_VALUE);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2019, 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
|
||||
|
@ -161,9 +161,9 @@ public class NestedLoopTest extends GraalCompilerTest {
|
||||
Assert.assertTrue(containsDirect(innerMostLoop, d, cfg));
|
||||
Assert.assertTrue(contains(rootLoop, d, cfg));
|
||||
Assert.assertTrue(contains(nestedLoop, d, cfg));
|
||||
Assert.assertEquals(rootExits, rootLoop.getExits().size());
|
||||
Assert.assertEquals(nestedExits, nestedLoop.getExits().size());
|
||||
Assert.assertEquals(innerExits, innerMostLoop.getExits().size());
|
||||
Assert.assertEquals(rootExits, rootLoop.getLoopExits().size());
|
||||
Assert.assertEquals(nestedExits, nestedLoop.getLoopExits().size());
|
||||
Assert.assertEquals(innerExits, innerMostLoop.getLoopExits().size());
|
||||
debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
|
||||
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SwitchCanonicalizerTest extends GraalCompilerTest {
|
||||
|
||||
public int divByPowerOf2(int n) {
|
||||
switch (n / 8) {
|
||||
case Integer.MAX_VALUE / 8 + 1:
|
||||
return hashCode();
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDivByPowerOf2() {
|
||||
shouldFoldSwitch("divByPowerOf2");
|
||||
}
|
||||
|
||||
public int divByNonPowerOf2(int n) {
|
||||
switch (n / 7) {
|
||||
case Integer.MAX_VALUE / 7 + 1:
|
||||
return hashCode();
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDivByNonPowerOf2() {
|
||||
shouldFoldSwitch("divByNonPowerOf2");
|
||||
}
|
||||
|
||||
public int remByPowerOf2(int n) {
|
||||
switch (n % 8) {
|
||||
case 9:
|
||||
return hashCode();
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemByPowerOf2() {
|
||||
shouldFoldSwitch("remByPowerOf2");
|
||||
}
|
||||
|
||||
public int remByPowerOf2PositiveX(int n) {
|
||||
int n0 = n > 0 ? 8 : 9;
|
||||
switch (n0 % 8) {
|
||||
case 9:
|
||||
return hashCode();
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemByPowerOf2PositiveX() {
|
||||
shouldFoldSwitch("remByPowerOf2PositiveX");
|
||||
}
|
||||
|
||||
public int remByPowerOf2NegativeX(int n) {
|
||||
int n0 = n > 0 ? -8 : -9;
|
||||
switch (n0 % 8) {
|
||||
case 9:
|
||||
return hashCode();
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemByPowerOf2NegativeX() {
|
||||
shouldFoldSwitch("remByPowerOf2NegativeX");
|
||||
}
|
||||
|
||||
public int remByNonPowerOf2(int n) {
|
||||
switch (n % 7) {
|
||||
case 9:
|
||||
return hashCode();
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemByNonPowerOf2() {
|
||||
shouldFoldSwitch("remByNonPowerOf2");
|
||||
}
|
||||
|
||||
private void shouldFoldSwitch(String methodName) {
|
||||
StructuredGraph graph = parseForCompile(getResolvedJavaMethod(methodName));
|
||||
new CanonicalizerPhase().apply(graph, getDefaultHighTierContext());
|
||||
assertFalse(graph.hasNode(IntegerSwitchNode.TYPE));
|
||||
}
|
||||
|
||||
}
|
@ -24,7 +24,7 @@
|
||||
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
|
||||
import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
|
@ -150,7 +150,8 @@ public class VerifyDebugUsage extends VerifyPhase<PhaseContext> {
|
||||
"org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl.compilePEGraph",
|
||||
"org.graalvm.compiler.core.test.VerifyDebugUsageTest$ValidDumpUsagePhase.run",
|
||||
"org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidConcatDumpUsagePhase.run",
|
||||
"org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidDumpUsagePhase.run"));
|
||||
"org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidDumpUsagePhase.run",
|
||||
"org.graalvm.compiler.hotspot.SymbolicSnippetEncoder.verifySnippetEncodeDecode"));
|
||||
|
||||
/**
|
||||
* The set of methods allowed to call a {@code Debug.dump(...)} method with the {@code level}
|
||||
@ -165,7 +166,8 @@ public class VerifyDebugUsage extends VerifyPhase<PhaseContext> {
|
||||
"org.graalvm.compiler.core.GraalCompiler.emitFrontEnd",
|
||||
"org.graalvm.compiler.phases.BasePhase.dumpAfter",
|
||||
"org.graalvm.compiler.replacements.ReplacementsImpl$GraphMaker.makeGraph",
|
||||
"org.graalvm.compiler.replacements.SnippetTemplate.instantiate"));
|
||||
"org.graalvm.compiler.replacements.SnippetTemplate.instantiate",
|
||||
"org.graalvm.compiler.hotspot.SymbolicSnippetEncoder.verifySnippetEncodeDecode"));
|
||||
|
||||
private void verifyParameters(StructuredGraph callerGraph, MethodCallTargetNode debugCallTarget, List<? extends ValueNode> args, ResolvedJavaType stringType, int startArgIdx,
|
||||
int varArgsIndex) {
|
||||
|
@ -25,6 +25,7 @@
|
||||
package org.graalvm.compiler.core.test.backend;
|
||||
|
||||
import org.graalvm.compiler.core.GraalCompiler;
|
||||
import org.graalvm.compiler.core.gen.LIRCompilerBackend;
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
|
||||
@ -52,7 +53,7 @@ public abstract class BackendTest extends GraalCompilerTest {
|
||||
throw debug.handle(e);
|
||||
}
|
||||
|
||||
LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), graph, null, null, createLIRSuites(graph.getOptions()));
|
||||
LIRGenerationResult lirGen = LIRCompilerBackend.emitLIR(getBackend(), graph, null, null, createLIRSuites(graph.getOptions()));
|
||||
return lirGen;
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ public final class RethrowDeoptMaterializeTest extends GraalCompilerTest {
|
||||
@SuppressWarnings("sync-override")
|
||||
@Override
|
||||
public final Throwable fillInStackTrace() {
|
||||
return null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,7 +293,7 @@ public class EscapeAnalysisTest extends EATestBase {
|
||||
@SuppressWarnings("sync-override")
|
||||
@Override
|
||||
public final Throwable fillInStackTrace() {
|
||||
return null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,42 +24,18 @@
|
||||
|
||||
package org.graalvm.compiler.core;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicSet;
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext;
|
||||
import org.graalvm.compiler.core.common.GraalOptions;
|
||||
import org.graalvm.compiler.core.common.PermanentBailoutException;
|
||||
import org.graalvm.compiler.core.common.RetryableBailoutException;
|
||||
import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder;
|
||||
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
|
||||
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
|
||||
import org.graalvm.compiler.core.common.util.CompilationAlarm;
|
||||
import org.graalvm.compiler.core.target.Backend;
|
||||
import org.graalvm.compiler.debug.CounterKey;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.debug.MethodFilter;
|
||||
import org.graalvm.compiler.debug.TimerKey;
|
||||
import org.graalvm.compiler.lir.LIR;
|
||||
import org.graalvm.compiler.lir.alloc.OutOfRegistersException;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
|
||||
import org.graalvm.compiler.lir.framemap.FrameMap;
|
||||
import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
|
||||
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
|
||||
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
|
||||
import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
|
||||
import org.graalvm.compiler.lir.phases.LIRSuites;
|
||||
import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
|
||||
import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
|
||||
import org.graalvm.compiler.nodes.cfg.Block;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
import org.graalvm.compiler.phases.OptimisticOptimizations;
|
||||
import org.graalvm.compiler.phases.PhaseSuite;
|
||||
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
|
||||
@ -70,17 +46,8 @@ import org.graalvm.compiler.phases.tiers.Suites;
|
||||
import org.graalvm.compiler.phases.tiers.TargetProvider;
|
||||
import org.graalvm.compiler.phases.util.Providers;
|
||||
|
||||
import jdk.vm.ci.code.RegisterConfig;
|
||||
import jdk.vm.ci.code.TargetDescription;
|
||||
import jdk.vm.ci.code.site.ConstantReference;
|
||||
import jdk.vm.ci.code.site.DataPatch;
|
||||
import jdk.vm.ci.meta.Assumptions;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.ProfilingInfo;
|
||||
import jdk.vm.ci.meta.ResolvedJavaField;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.VMConstant;
|
||||
|
||||
/**
|
||||
* Static methods for orchestrating the compilation of a {@linkplain StructuredGraph graph}.
|
||||
@ -89,9 +56,6 @@ public class GraalCompiler {
|
||||
|
||||
private static final TimerKey CompilerTimer = DebugContext.timer("GraalCompiler").doc("Time spent in compilation (excludes code installation).");
|
||||
private static final TimerKey FrontEnd = DebugContext.timer("FrontEnd").doc("Time spent processing HIR.");
|
||||
private static final TimerKey EmitLIR = DebugContext.timer("EmitLIR").doc("Time spent generating LIR from HIR.");
|
||||
private static final TimerKey EmitCode = DebugContext.timer("EmitCode").doc("Time spent generating machine code from LIR.");
|
||||
private static final TimerKey BackEnd = DebugContext.timer("BackEnd").doc("Time spent in EmitLIR and EmitCode.");
|
||||
|
||||
/**
|
||||
* Encapsulates all the inputs to a {@linkplain GraalCompiler#compile(Request) compilation}.
|
||||
@ -178,7 +142,7 @@ public class GraalCompiler {
|
||||
assert !r.graph.isFrozen();
|
||||
try (DebugContext.Scope s0 = debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); DebugCloseable a = CompilerTimer.start(debug)) {
|
||||
emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites);
|
||||
emitBackEnd(r.graph, null, r.installedCodeOwner, r.backend, r.compilationResult, r.factory, null, r.lirSuites);
|
||||
r.backend.emitBackEnd(r.graph, null, r.installedCodeOwner, r.compilationResult, r.factory, null, r.lirSuites);
|
||||
if (r.verifySourcePositions) {
|
||||
assert r.graph.verifySourcePositions(true);
|
||||
}
|
||||
@ -275,85 +239,6 @@ public class GraalCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
public static <T extends CompilationResult> void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult,
|
||||
CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) {
|
||||
DebugContext debug = graph.getDebug();
|
||||
try (DebugContext.Scope s = debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start(debug)) {
|
||||
LIRGenerationResult lirGen = null;
|
||||
lirGen = emitLIR(backend, graph, stub, registerConfig, lirSuites);
|
||||
try (DebugContext.Scope s2 = debug.scope("CodeGen", lirGen, lirGen.getLIR())) {
|
||||
int bytecodeSize = graph.method() == null ? 0 : graph.getBytecodeSize();
|
||||
compilationResult.setHasUnsafeAccess(graph.hasUnsafeAccess());
|
||||
emitCode(backend, graph.getAssumptions(), graph.method(), graph.getMethods(), graph.getFields(), bytecodeSize, lirGen, compilationResult, installedCodeOwner, factory);
|
||||
} catch (Throwable e) {
|
||||
throw debug.handle(e);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
throw debug.handle(e);
|
||||
} finally {
|
||||
graph.checkCancellation();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) {
|
||||
String registerPressure = GraalOptions.RegisterPressure.getValue(graph.getOptions());
|
||||
String[] allocationRestrictedTo = registerPressure == null ? null : registerPressure.split(",");
|
||||
try {
|
||||
return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo);
|
||||
} catch (OutOfRegistersException e) {
|
||||
if (allocationRestrictedTo != null) {
|
||||
allocationRestrictedTo = null;
|
||||
return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo);
|
||||
}
|
||||
/* If the re-execution fails we convert the exception into a "hard" failure */
|
||||
throw new GraalError(e);
|
||||
} finally {
|
||||
graph.checkCancellation();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites,
|
||||
String[] allocationRestrictedTo) {
|
||||
DebugContext debug = graph.getDebug();
|
||||
try (DebugContext.Scope ds = debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start(debug)) {
|
||||
assert !graph.hasValueProxies();
|
||||
ScheduleResult schedule = graph.getLastSchedule();
|
||||
Block[] blocks = schedule.getCFG().getBlocks();
|
||||
Block startBlock = schedule.getCFG().getStartBlock();
|
||||
assert startBlock != null;
|
||||
assert startBlock.getPredecessorCount() == 0;
|
||||
|
||||
AbstractBlockBase<?>[] codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock);
|
||||
AbstractBlockBase<?>[] linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock);
|
||||
LIR lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions(), graph.getDebug());
|
||||
|
||||
FrameMapBuilder frameMapBuilder = backend.newFrameMapBuilder(registerConfig);
|
||||
LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(graph.compilationId(), lir, frameMapBuilder, graph, stub);
|
||||
LIRGeneratorTool lirGen = backend.newLIRGenerator(lirGenRes);
|
||||
NodeLIRBuilderTool nodeLirGen = backend.newNodeLIRBuilder(graph, lirGen);
|
||||
|
||||
// LIR generation
|
||||
LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule);
|
||||
new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context);
|
||||
|
||||
try (DebugContext.Scope s = debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) {
|
||||
// Dump LIR along with HIR (the LIR is looked up from context)
|
||||
debug.dump(DebugContext.BASIC_LEVEL, graph.getLastSchedule(), "After LIR generation");
|
||||
LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo));
|
||||
return result;
|
||||
} catch (Throwable e) {
|
||||
throw debug.handle(e);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
throw debug.handle(e);
|
||||
} finally {
|
||||
graph.checkCancellation();
|
||||
}
|
||||
}
|
||||
|
||||
protected static <T extends CompilationResult> String getCompilationUnitName(StructuredGraph graph, T compilationResult) {
|
||||
if (compilationResult != null && compilationResult.getName() != null) {
|
||||
return compilationResult.getName();
|
||||
@ -364,70 +249,4 @@ public class GraalCompiler {
|
||||
}
|
||||
return method.format("%H.%n(%p)");
|
||||
}
|
||||
|
||||
public static LIRGenerationResult emitLowLevel(TargetDescription target, LIRGenerationResult lirGenRes, LIRGeneratorTool lirGen, LIRSuites lirSuites,
|
||||
RegisterAllocationConfig registerAllocationConfig) {
|
||||
DebugContext debug = lirGenRes.getLIR().getDebug();
|
||||
PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen);
|
||||
lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, preAllocOptContext);
|
||||
debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PreAllocationOptimizationStage");
|
||||
|
||||
AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig);
|
||||
lirSuites.getAllocationStage().apply(target, lirGenRes, allocContext);
|
||||
debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After AllocationStage");
|
||||
|
||||
PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen);
|
||||
lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, postAllocOptContext);
|
||||
debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PostAllocationOptimizationStage");
|
||||
|
||||
return lirGenRes;
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Collection<ResolvedJavaMethod> inlinedMethods, EconomicSet<ResolvedJavaField> accessedFields,
|
||||
int bytecodeSize, LIRGenerationResult lirGenRes,
|
||||
CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) {
|
||||
DebugContext debug = lirGenRes.getLIR().getDebug();
|
||||
try (DebugCloseable a = EmitCode.start(debug)) {
|
||||
FrameMap frameMap = lirGenRes.getFrameMap();
|
||||
CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory);
|
||||
backend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner);
|
||||
if (assumptions != null && !assumptions.isEmpty()) {
|
||||
compilationResult.setAssumptions(assumptions.toArray());
|
||||
}
|
||||
if (rootMethod != null) {
|
||||
compilationResult.setMethods(rootMethod, inlinedMethods);
|
||||
compilationResult.setFields(accessedFields);
|
||||
compilationResult.setBytecodeSize(bytecodeSize);
|
||||
}
|
||||
crb.finish();
|
||||
if (debug.isCountEnabled()) {
|
||||
List<DataPatch> ldp = compilationResult.getDataPatches();
|
||||
JavaKind[] kindValues = JavaKind.values();
|
||||
CounterKey[] dms = new CounterKey[kindValues.length];
|
||||
for (int i = 0; i < dms.length; i++) {
|
||||
dms[i] = DebugContext.counter("DataPatches-%s", kindValues[i]);
|
||||
}
|
||||
|
||||
for (DataPatch dp : ldp) {
|
||||
JavaKind kind = JavaKind.Illegal;
|
||||
if (dp.reference instanceof ConstantReference) {
|
||||
VMConstant constant = ((ConstantReference) dp.reference).getConstant();
|
||||
if (constant instanceof JavaConstant) {
|
||||
kind = ((JavaConstant) constant).getJavaKind();
|
||||
}
|
||||
}
|
||||
dms[kind.ordinal()].add(debug, 1);
|
||||
}
|
||||
|
||||
DebugContext.counter("CompilationResults").increment(debug);
|
||||
DebugContext.counter("CodeBytesEmitted").add(debug, compilationResult.getTargetCodeSize());
|
||||
DebugContext.counter("InfopointsEmitted").add(debug, compilationResult.getInfopoints().size());
|
||||
DebugContext.counter("DataPatches").add(debug, ldp.size());
|
||||
DebugContext.counter("ExceptionHandlersEmitted").add(debug, compilationResult.getExceptionHandlers().size());
|
||||
}
|
||||
|
||||
debug.dump(DebugContext.BASIC_LEVEL, compilationResult, "After code generation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.core.gen;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicSet;
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.core.LIRGenerationPhase;
|
||||
import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext;
|
||||
import org.graalvm.compiler.core.common.GraalOptions;
|
||||
import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder;
|
||||
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
|
||||
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
|
||||
import org.graalvm.compiler.core.target.Backend;
|
||||
import org.graalvm.compiler.debug.CounterKey;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.debug.TimerKey;
|
||||
import org.graalvm.compiler.lir.LIR;
|
||||
import org.graalvm.compiler.lir.alloc.OutOfRegistersException;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
|
||||
import org.graalvm.compiler.lir.framemap.FrameMap;
|
||||
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
|
||||
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
|
||||
import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
|
||||
import org.graalvm.compiler.lir.phases.LIRSuites;
|
||||
import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
|
||||
import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
|
||||
import org.graalvm.compiler.nodes.cfg.Block;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
|
||||
import jdk.vm.ci.code.RegisterConfig;
|
||||
import jdk.vm.ci.code.TargetDescription;
|
||||
import jdk.vm.ci.code.site.ConstantReference;
|
||||
import jdk.vm.ci.code.site.DataPatch;
|
||||
import jdk.vm.ci.meta.Assumptions;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.ResolvedJavaField;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.SpeculationLog;
|
||||
import jdk.vm.ci.meta.VMConstant;
|
||||
|
||||
public class LIRCompilerBackend {
|
||||
private static final TimerKey EmitLIR = DebugContext.timer("EmitLIR").doc("Time spent generating LIR from HIR.");
|
||||
private static final TimerKey EmitCode = DebugContext.timer("EmitCode").doc("Time spent generating machine code from LIR.");
|
||||
private static final TimerKey BackEnd = DebugContext.timer("BackEnd").doc("Time spent in EmitLIR and EmitCode.");
|
||||
|
||||
@SuppressWarnings("try")
|
||||
public static <T extends CompilationResult> void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult,
|
||||
CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) {
|
||||
DebugContext debug = graph.getDebug();
|
||||
try (DebugContext.Scope s = debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start(debug)) {
|
||||
LIRGenerationResult lirGen = null;
|
||||
lirGen = emitLIR(backend, graph, stub, registerConfig, lirSuites);
|
||||
try (DebugContext.Scope s2 = debug.scope("CodeGen", lirGen, lirGen.getLIR())) {
|
||||
int bytecodeSize = graph.method() == null ? 0 : graph.getBytecodeSize();
|
||||
compilationResult.setHasUnsafeAccess(graph.hasUnsafeAccess());
|
||||
emitCode(backend,
|
||||
graph.getAssumptions(),
|
||||
graph.method(),
|
||||
graph.getMethods(),
|
||||
graph.getFields(),
|
||||
graph.getSpeculationLog(),
|
||||
bytecodeSize,
|
||||
lirGen,
|
||||
compilationResult,
|
||||
installedCodeOwner,
|
||||
factory);
|
||||
} catch (Throwable e) {
|
||||
throw debug.handle(e);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
throw debug.handle(e);
|
||||
} finally {
|
||||
graph.checkCancellation();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) {
|
||||
String registerPressure = GraalOptions.RegisterPressure.getValue(graph.getOptions());
|
||||
String[] allocationRestrictedTo = registerPressure == null ? null : registerPressure.split(",");
|
||||
try {
|
||||
return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo);
|
||||
} catch (OutOfRegistersException e) {
|
||||
if (allocationRestrictedTo != null) {
|
||||
allocationRestrictedTo = null;
|
||||
return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo);
|
||||
}
|
||||
/* If the re-execution fails we convert the exception into a "hard" failure */
|
||||
throw new GraalError(e);
|
||||
} finally {
|
||||
graph.checkCancellation();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites,
|
||||
String[] allocationRestrictedTo) {
|
||||
DebugContext debug = graph.getDebug();
|
||||
try (DebugContext.Scope ds = debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start(debug)) {
|
||||
assert !graph.hasValueProxies();
|
||||
|
||||
ScheduleResult schedule = graph.getLastSchedule();
|
||||
Block[] blocks = schedule.getCFG().getBlocks();
|
||||
Block startBlock = schedule.getCFG().getStartBlock();
|
||||
assert startBlock != null;
|
||||
assert startBlock.getPredecessorCount() == 0;
|
||||
|
||||
AbstractBlockBase<?>[] codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock);
|
||||
AbstractBlockBase<?>[] linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock);
|
||||
LIR lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions(), graph.getDebug());
|
||||
|
||||
LIRGenerationProvider lirBackend = (LIRGenerationProvider) backend;
|
||||
LIRGenerationResult lirGenRes = lirBackend.newLIRGenerationResult(graph.compilationId(), lir, registerConfig, graph, stub);
|
||||
LIRGeneratorTool lirGen = lirBackend.newLIRGenerator(lirGenRes);
|
||||
NodeLIRBuilderTool nodeLirGen = lirBackend.newNodeLIRBuilder(graph, lirGen);
|
||||
|
||||
// LIR generation
|
||||
LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule);
|
||||
new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context);
|
||||
|
||||
try (DebugContext.Scope s = debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) {
|
||||
// Dump LIR along with HIR (the LIR is looked up from context)
|
||||
debug.dump(DebugContext.BASIC_LEVEL, graph.getLastSchedule(), "After LIR generation");
|
||||
LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo));
|
||||
return result;
|
||||
} catch (Throwable e) {
|
||||
throw debug.handle(e);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
throw debug.handle(e);
|
||||
} finally {
|
||||
graph.checkCancellation();
|
||||
}
|
||||
}
|
||||
|
||||
private static LIRGenerationResult emitLowLevel(TargetDescription target, LIRGenerationResult lirGenRes, LIRGeneratorTool lirGen, LIRSuites lirSuites,
|
||||
RegisterAllocationConfig registerAllocationConfig) {
|
||||
DebugContext debug = lirGenRes.getLIR().getDebug();
|
||||
PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen);
|
||||
lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, preAllocOptContext);
|
||||
debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PreAllocationOptimizationStage");
|
||||
|
||||
AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig);
|
||||
lirSuites.getAllocationStage().apply(target, lirGenRes, allocContext);
|
||||
debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After AllocationStage");
|
||||
|
||||
PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen);
|
||||
lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, postAllocOptContext);
|
||||
debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PostAllocationOptimizationStage");
|
||||
|
||||
return lirGenRes;
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
public static void emitCode(Backend backend,
|
||||
Assumptions assumptions,
|
||||
ResolvedJavaMethod rootMethod,
|
||||
Collection<ResolvedJavaMethod> inlinedMethods,
|
||||
EconomicSet<ResolvedJavaField> accessedFields,
|
||||
SpeculationLog speculationLog,
|
||||
int bytecodeSize,
|
||||
LIRGenerationResult lirGenRes,
|
||||
CompilationResult compilationResult,
|
||||
ResolvedJavaMethod installedCodeOwner,
|
||||
CompilationResultBuilderFactory factory) {
|
||||
DebugContext debug = lirGenRes.getLIR().getDebug();
|
||||
try (DebugCloseable a = EmitCode.start(debug)) {
|
||||
LIRGenerationProvider lirBackend = (LIRGenerationProvider) backend;
|
||||
|
||||
FrameMap frameMap = lirGenRes.getFrameMap();
|
||||
CompilationResultBuilder crb = lirBackend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory);
|
||||
lirBackend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner);
|
||||
if (assumptions != null && !assumptions.isEmpty()) {
|
||||
compilationResult.setAssumptions(assumptions.toArray());
|
||||
}
|
||||
if (rootMethod != null) {
|
||||
compilationResult.setMethods(rootMethod, inlinedMethods);
|
||||
compilationResult.setFields(accessedFields);
|
||||
compilationResult.setBytecodeSize(bytecodeSize);
|
||||
}
|
||||
if (speculationLog != null) {
|
||||
compilationResult.setSpeculationLog(speculationLog);
|
||||
}
|
||||
crb.finish();
|
||||
if (debug.isCountEnabled()) {
|
||||
List<DataPatch> ldp = compilationResult.getDataPatches();
|
||||
JavaKind[] kindValues = JavaKind.values();
|
||||
CounterKey[] dms = new CounterKey[kindValues.length];
|
||||
for (int i = 0; i < dms.length; i++) {
|
||||
dms[i] = DebugContext.counter("DataPatches-%s", kindValues[i]);
|
||||
}
|
||||
|
||||
for (DataPatch dp : ldp) {
|
||||
JavaKind kind = JavaKind.Illegal;
|
||||
if (dp.reference instanceof ConstantReference) {
|
||||
VMConstant constant = ((ConstantReference) dp.reference).getConstant();
|
||||
if (constant instanceof JavaConstant) {
|
||||
kind = ((JavaConstant) constant).getJavaKind();
|
||||
}
|
||||
}
|
||||
dms[kind.ordinal()].add(debug, 1);
|
||||
}
|
||||
|
||||
DebugContext.counter("CompilationResults").increment(debug);
|
||||
DebugContext.counter("CodeBytesEmitted").add(debug, compilationResult.getTargetCodeSize());
|
||||
DebugContext.counter("InfopointsEmitted").add(debug, compilationResult.getInfopoints().size());
|
||||
DebugContext.counter("DataPatches").add(debug, ldp.size());
|
||||
DebugContext.counter("ExceptionHandlersEmitted").add(debug, compilationResult.getExceptionHandlers().size());
|
||||
}
|
||||
|
||||
debug.dump(DebugContext.BASIC_LEVEL, compilationResult, "After code generation");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.core.gen;
|
||||
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.lir.LIR;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
|
||||
import org.graalvm.compiler.lir.framemap.FrameMap;
|
||||
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
|
||||
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
|
||||
import jdk.vm.ci.code.RegisterConfig;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
/**
|
||||
* Provides compiler backend-specific generation helpers for the {@link LIRCompilerBackend}.
|
||||
*/
|
||||
public interface LIRGenerationProvider {
|
||||
LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes);
|
||||
|
||||
LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph,
|
||||
Object stub);
|
||||
|
||||
NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen);
|
||||
|
||||
/**
|
||||
* Creates the object used to fill in the details of a given compilation result.
|
||||
*/
|
||||
CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, FrameMap frameMap, CompilationResult compilationResult,
|
||||
CompilationResultBuilderFactory factory);
|
||||
|
||||
/**
|
||||
* Emits the code for a given graph.
|
||||
*
|
||||
* @param installedCodeOwner the method the compiled code will be associated with once
|
||||
* installed. This argument can be null.
|
||||
*/
|
||||
void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner);
|
||||
}
|
@ -768,4 +768,13 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio
|
||||
public LIRGeneratorTool getLIRGeneratorTool() {
|
||||
return gen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitReadExceptionObject(ValueNode node) {
|
||||
LIRGeneratorTool lirGenTool = getLIRGeneratorTool();
|
||||
Value returnRegister = lirGenTool.getRegisterConfig().getReturnRegister(node.getStackKind()).asValue(
|
||||
LIRKind.fromJavaKind(lirGenTool.target().arch, node.getStackKind()));
|
||||
lirGenTool.emitIncomingValues(new Value[]{returnRegister});
|
||||
setResult(node, lirGenTool.emitMove(returnRegister));
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ import org.graalvm.compiler.options.OptionType;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.phases.PhaseSuite;
|
||||
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
|
||||
import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
|
||||
import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
|
||||
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
|
||||
import org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase;
|
||||
import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
|
||||
|
@ -39,6 +39,7 @@ import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
|
||||
import org.graalvm.compiler.phases.common.ExpandLogicPhase;
|
||||
import org.graalvm.compiler.phases.common.FixReadsPhase;
|
||||
import org.graalvm.compiler.phases.common.LoweringPhase;
|
||||
import org.graalvm.compiler.phases.common.OptimizeDivPhase;
|
||||
import org.graalvm.compiler.phases.common.ProfileCompiledMethodsPhase;
|
||||
import org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase;
|
||||
import org.graalvm.compiler.phases.common.UseTrappingNullChecksPhase;
|
||||
@ -72,6 +73,8 @@ public class LowTier extends PhaseSuite<LowTierContext> {
|
||||
|
||||
appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER));
|
||||
|
||||
appendPhase(new OptimizeDivPhase());
|
||||
|
||||
appendPhase(new ExpandLogicPhase());
|
||||
|
||||
appendPhase(new FixReadsPhase(true, new SchedulePhase(GraalOptions.StressTestEarlyReads.getValue(options) ? SchedulingStrategy.EARLIEST : SchedulingStrategy.LATEST_OUT_OF_LOOPS)));
|
||||
|
@ -26,24 +26,17 @@ package org.graalvm.compiler.core.target;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicSet;
|
||||
import org.graalvm.compiler.asm.Assembler;
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
|
||||
import org.graalvm.compiler.core.gen.LIRCompilerBackend;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.lir.LIR;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
|
||||
import org.graalvm.compiler.lir.framemap.FrameMap;
|
||||
import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
|
||||
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
|
||||
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
|
||||
import org.graalvm.compiler.lir.phases.LIRSuites;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.phases.tiers.SuitesProvider;
|
||||
import org.graalvm.compiler.phases.tiers.TargetProvider;
|
||||
@ -54,7 +47,6 @@ import jdk.vm.ci.code.CodeCacheProvider;
|
||||
import jdk.vm.ci.code.CompilationRequest;
|
||||
import jdk.vm.ci.code.CompiledCode;
|
||||
import jdk.vm.ci.code.InstalledCode;
|
||||
import jdk.vm.ci.code.Register;
|
||||
import jdk.vm.ci.code.RegisterConfig;
|
||||
import jdk.vm.ci.code.TargetDescription;
|
||||
import jdk.vm.ci.code.ValueKindFactory;
|
||||
@ -62,7 +54,6 @@ import jdk.vm.ci.meta.ConstantReflectionProvider;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.SpeculationLog;
|
||||
|
||||
/**
|
||||
* Represents a compiler backend for Graal.
|
||||
@ -116,12 +107,6 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
|
||||
return LIRKind.fromJavaKind(getTarget().arch, javaKind);
|
||||
}
|
||||
|
||||
/**
|
||||
* The given registerConfig is optional, in case null is passed the default RegisterConfig from
|
||||
* the CodeCacheProvider will be used.
|
||||
*/
|
||||
public abstract FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig);
|
||||
|
||||
/**
|
||||
* Creates a new configuration for register allocation.
|
||||
*
|
||||
@ -130,26 +115,6 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
|
||||
*/
|
||||
public abstract RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo);
|
||||
|
||||
public abstract FrameMap newFrameMap(RegisterConfig registerConfig);
|
||||
|
||||
public abstract LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes);
|
||||
|
||||
public abstract LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph,
|
||||
Object stub);
|
||||
|
||||
public abstract NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen);
|
||||
|
||||
/**
|
||||
* Creates the assembler used to emit the machine code.
|
||||
*/
|
||||
protected abstract Assembler createAssembler(FrameMap frameMap);
|
||||
|
||||
/**
|
||||
* Creates the object used to fill in the details of a given compilation result.
|
||||
*/
|
||||
public abstract CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, FrameMap frameMap, CompilationResult compilationResult,
|
||||
CompilationResultBuilderFactory factory);
|
||||
|
||||
/**
|
||||
* Turns a Graal {@link CompilationResult} into a {@link CompiledCode} object that can be passed
|
||||
* to the VM for code installation.
|
||||
@ -158,21 +123,28 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
|
||||
|
||||
/**
|
||||
* @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest,
|
||||
* CompilationResult, SpeculationLog, InstalledCode, boolean, Object[])
|
||||
* CompilationResult, InstalledCode, boolean, Object[])
|
||||
*/
|
||||
public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult,
|
||||
SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault) {
|
||||
return createInstalledCode(debug, method, null, compilationResult, speculationLog, predefinedInstalledCode, isDefault, null);
|
||||
public InstalledCode createInstalledCode(DebugContext debug,
|
||||
ResolvedJavaMethod method,
|
||||
CompilationResult compilationResult,
|
||||
InstalledCode predefinedInstalledCode,
|
||||
boolean isDefault) {
|
||||
return createInstalledCode(debug, method, null, compilationResult, predefinedInstalledCode, isDefault, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest,
|
||||
* CompilationResult, SpeculationLog, InstalledCode, boolean, Object[])
|
||||
* CompilationResult, InstalledCode, boolean, Object[])
|
||||
*/
|
||||
@SuppressWarnings("try")
|
||||
public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult,
|
||||
SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault) {
|
||||
return createInstalledCode(debug, method, compilationRequest, compilationResult, speculationLog, predefinedInstalledCode, isDefault, null);
|
||||
public InstalledCode createInstalledCode(DebugContext debug,
|
||||
ResolvedJavaMethod method,
|
||||
CompilationRequest compilationRequest,
|
||||
CompilationResult compilationResult,
|
||||
InstalledCode predefinedInstalledCode,
|
||||
boolean isDefault) {
|
||||
return createInstalledCode(debug, method, compilationRequest, compilationResult, predefinedInstalledCode, isDefault, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -185,7 +157,6 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
|
||||
* @param predefinedInstalledCode a pre-allocated {@link InstalledCode} object to use as a
|
||||
* reference to the installed code. If {@code null}, a new {@link InstalledCode}
|
||||
* object will be created.
|
||||
* @param speculationLog the speculation log to be used
|
||||
* @param isDefault specifies if the installed code should be made the default implementation of
|
||||
* {@code compRequest.getMethod()}. The default implementation for a method is the
|
||||
* code executed for standard calls to the method. This argument is ignored if
|
||||
@ -198,8 +169,13 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
|
||||
* {@link InstalledCode} object
|
||||
*/
|
||||
@SuppressWarnings("try")
|
||||
public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult,
|
||||
SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault, Object[] context) {
|
||||
public InstalledCode createInstalledCode(DebugContext debug,
|
||||
ResolvedJavaMethod method,
|
||||
CompilationRequest compilationRequest,
|
||||
CompilationResult compilationResult,
|
||||
InstalledCode predefinedInstalledCode,
|
||||
boolean isDefault,
|
||||
Object[] context) {
|
||||
Object[] debugContext = context != null ? context : new Object[]{getProviders().getCodeCache(), method, compilationResult};
|
||||
CodeInstallationTask[] tasks;
|
||||
synchronized (this) {
|
||||
@ -215,7 +191,7 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
|
||||
try {
|
||||
preCodeInstallationTasks(tasks, compilationResult);
|
||||
CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult, isDefault, debug.getOptions());
|
||||
installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault);
|
||||
installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, compilationResult.getSpeculationLog(), isDefault);
|
||||
assert predefinedInstalledCode == null || installedCode == predefinedInstalledCode;
|
||||
} catch (Throwable t) {
|
||||
failCodeInstallationTasks(tasks, t);
|
||||
@ -259,12 +235,15 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
|
||||
* @param method the method compiled to produce {@code compiledCode} or {@code null} if the
|
||||
* input to {@code compResult} was not a {@link ResolvedJavaMethod}
|
||||
* @param compilationRequest the request or {@code null}
|
||||
* @param compilationResult the code to be compiled
|
||||
* @param compilationResult the compiled code
|
||||
* @return a reference to the compiled and ready-to-run installed code
|
||||
* @throws BailoutException if the code installation failed
|
||||
*/
|
||||
public InstalledCode addInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult) {
|
||||
return createInstalledCode(debug, method, compilationRequest, compilationResult, null, null, false);
|
||||
public InstalledCode addInstalledCode(DebugContext debug,
|
||||
ResolvedJavaMethod method,
|
||||
CompilationRequest compilationRequest,
|
||||
CompilationResult compilationResult) {
|
||||
return createInstalledCode(debug, method, compilationRequest, compilationResult, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -273,29 +252,15 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
|
||||
*
|
||||
* @param method the method compiled to produce {@code compiledCode} or {@code null} if the
|
||||
* input to {@code compResult} was not a {@link ResolvedJavaMethod}
|
||||
* @param compilationResult the code to be compiled
|
||||
* @param compilationResult the compiled code
|
||||
* @return a reference to the compiled and ready-to-run installed code
|
||||
* @throws BailoutException if the code installation failed
|
||||
*/
|
||||
public InstalledCode createDefaultInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult) {
|
||||
return createInstalledCode(debug, method, compilationResult, null, null, true);
|
||||
System.out.println(compilationResult.getSpeculationLog());
|
||||
return createInstalledCode(debug, method, compilationResult, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits the code for a given graph.
|
||||
*
|
||||
* @param installedCodeOwner the method the compiled code will be associated with once
|
||||
* installed. This argument can be null.
|
||||
*/
|
||||
public abstract void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner);
|
||||
|
||||
/**
|
||||
* Translates a set of registers from the callee's perspective to the caller's perspective. This
|
||||
* is needed for architectures where input/output registers are renamed during a call (e.g.
|
||||
* register windows on SPARC). Registers which are not visible by the caller are removed.
|
||||
*/
|
||||
public abstract EconomicSet<Register> translateToCallerRegisters(EconomicSet<Register> calleeRegisters);
|
||||
|
||||
/**
|
||||
* Gets the compilation id for a given {@link ResolvedJavaMethod}. Returns
|
||||
* {@code CompilationIdentifier#INVALID_COMPILATION_ID} in case there is no such id.
|
||||
@ -306,6 +271,15 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
|
||||
return CompilationIdentifier.INVALID_COMPILATION_ID;
|
||||
}
|
||||
|
||||
public void emitBackEnd(StructuredGraph graph,
|
||||
Object stub,
|
||||
ResolvedJavaMethod installedCodeOwner,
|
||||
CompilationResult compilationResult,
|
||||
CompilationResultBuilderFactory factory,
|
||||
RegisterConfig config, LIRSuites lirSuites) {
|
||||
LIRCompilerBackend.emitBackEnd(graph, stub, installedCodeOwner, this, compilationResult, factory, config, lirSuites);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encapsulates custom tasks done before and after code installation.
|
||||
*/
|
||||
|
@ -450,11 +450,11 @@ public final class DebugContext implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
public Path getDumpPath(String extension, boolean directory) {
|
||||
public Path getDumpPath(String extension, boolean createMissingDirectory) {
|
||||
try {
|
||||
String id = description == null ? null : description.identifier;
|
||||
String label = description == null ? null : description.getLabel();
|
||||
Path result = PathUtilities.createUnique(immutable.options, DumpPath, id, label, extension, directory);
|
||||
Path result = PathUtilities.createUnique(immutable.options, DumpPath, id, label, extension, createMissingDirectory);
|
||||
if (ShowDumpFiles.getValue(immutable.options)) {
|
||||
TTY.println("Dumping debug output to %s", result.toAbsolutePath().toString());
|
||||
}
|
||||
@ -807,8 +807,9 @@ public final class DebugContext implements AutoCloseable {
|
||||
return true;
|
||||
}
|
||||
return !currentScope.isTopLevel();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return immutable.scopesEnabled && currentScope == null;
|
||||
}
|
||||
|
||||
class DisabledScope implements DebugContext.Scope {
|
||||
|
@ -30,6 +30,7 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import org.graalvm.compiler.options.EnumOptionKey;
|
||||
import org.graalvm.compiler.options.Option;
|
||||
import org.graalvm.compiler.options.OptionKey;
|
||||
import org.graalvm.compiler.options.OptionType;
|
||||
@ -40,20 +41,28 @@ import org.graalvm.compiler.serviceprovider.GraalServices;
|
||||
* Options that configure a {@link DebugContext} and related functionality.
|
||||
*/
|
||||
public class DebugOptions {
|
||||
static class DeprecatedOptionKey<T> extends OptionKey<T> {
|
||||
private final OptionKey<T> replacement;
|
||||
|
||||
DeprecatedOptionKey(OptionKey<T> replacement) {
|
||||
super(replacement.getDefaultValue());
|
||||
this.replacement = replacement;
|
||||
}
|
||||
/**
|
||||
* Values for the {@link DebugOptions#PrintGraph} option denoting where graphs dumped as a
|
||||
* result of the {@link DebugOptions#Dump} option are sent.
|
||||
*/
|
||||
public enum PrintGraphTarget {
|
||||
/**
|
||||
* Dump graphs to files.
|
||||
*/
|
||||
File,
|
||||
|
||||
@Override
|
||||
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, T oldValue, T newValue) {
|
||||
// Ideally we'd use TTY here but it may not yet be initialized.
|
||||
System.err.printf("Warning: the %s option is deprecated - use %s instead%n", getName(), replacement.getName());
|
||||
replacement.update(values, newValue);
|
||||
}
|
||||
/**
|
||||
* Dump graphs to the network. The network destination is specified by the
|
||||
* {@link DebugOptions#PrintGraphHost} and {@link DebugOptions#PrintGraphPort} options. If a
|
||||
* network connection cannot be opened, dumping falls back to {@link #File} dumping.
|
||||
*/
|
||||
Network,
|
||||
|
||||
/**
|
||||
* Do not dump graphs.
|
||||
*/
|
||||
Disable;
|
||||
}
|
||||
|
||||
// @formatter:off
|
||||
@ -118,7 +127,7 @@ public class DebugOptions {
|
||||
public static final OptionKey<Boolean> LogVerbose = new OptionKey<>(false);
|
||||
|
||||
@Option(help = "The directory where various Graal dump files are written.")
|
||||
public static final OptionKey<String> DumpPath = new OptionKey<>("dumps");
|
||||
public static final OptionKey<String> DumpPath = new OptionKey<>("graal_dumps");
|
||||
@Option(help = "Print the name of each dump file path as it's created.")
|
||||
public static final OptionKey<Boolean> ShowDumpFiles = new OptionKey<>(false);
|
||||
|
||||
@ -127,15 +136,30 @@ public class DebugOptions {
|
||||
@Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> PrintBackendCFG = new OptionKey<>(true);
|
||||
|
||||
@Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> PrintGraph = new OptionKey<>(true);
|
||||
@Option(help = "Print graphs to files instead of sending them over the network.", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> PrintGraphFile = new OptionKey<>(false);
|
||||
@Option(help = "file:doc-files/PrintGraphHelp.txt", type = OptionType.Debug)
|
||||
public static final EnumOptionKey<PrintGraphTarget> PrintGraph = new EnumOptionKey<>(PrintGraphTarget.File);
|
||||
|
||||
@Option(help = "Setting to true sets PrintGraph=file, setting to false sets PrintGraph=network", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> PrintGraphFile = new OptionKey<Boolean>(true) {
|
||||
@Override
|
||||
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean oldValue, Boolean newValue) {
|
||||
PrintGraphTarget v = PrintGraph.getValueOrDefault(values);
|
||||
if (newValue.booleanValue()) {
|
||||
if (v != PrintGraphTarget.File) {
|
||||
PrintGraph.update(values, PrintGraphTarget.File);
|
||||
}
|
||||
} else {
|
||||
if (v != PrintGraphTarget.Network) {
|
||||
PrintGraph.update(values, PrintGraphTarget.Network);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug)
|
||||
public static final OptionKey<String> PrintGraphHost = new OptionKey<>("127.0.0.1");
|
||||
@Option(help = "Port part of the address to which graphs are dumped in binary format.", type = OptionType.Debug)
|
||||
public static final OptionKey<Integer> PrintBinaryGraphPort = new OptionKey<>(4445);
|
||||
public static final OptionKey<Integer> PrintGraphPort = new OptionKey<>(4445);
|
||||
@Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> PrintGraphWithSchedule = new OptionKey<>(false);
|
||||
|
||||
|
@ -24,6 +24,10 @@
|
||||
|
||||
package org.graalvm.compiler.debug;
|
||||
|
||||
import static org.graalvm.compiler.debug.DebugOptions.PrintGraphHost;
|
||||
import static org.graalvm.compiler.debug.DebugOptions.PrintGraphPort;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.InetSocketAddress;
|
||||
@ -35,10 +39,12 @@ import java.nio.channels.WritableByteChannel;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.function.Supplier;
|
||||
import static org.graalvm.compiler.debug.DebugOptions.PrintBinaryGraphPort;
|
||||
import static org.graalvm.compiler.debug.DebugOptions.PrintGraphHost;
|
||||
|
||||
import org.graalvm.compiler.debug.DebugOptions.PrintGraphTarget;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
|
||||
import jdk.vm.ci.common.NativeImageReinitialize;
|
||||
|
||||
final class IgvDumpChannel implements WritableByteChannel {
|
||||
private final Supplier<Path> pathProvider;
|
||||
private final OptionValues options;
|
||||
@ -52,7 +58,8 @@ final class IgvDumpChannel implements WritableByteChannel {
|
||||
|
||||
@Override
|
||||
public int write(ByteBuffer src) throws IOException {
|
||||
return channel().write(src);
|
||||
WritableByteChannel channel = channel();
|
||||
return channel == null ? 0 : channel.write(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -77,10 +84,13 @@ final class IgvDumpChannel implements WritableByteChannel {
|
||||
throw new IOException();
|
||||
}
|
||||
if (sharedChannel == null) {
|
||||
if (DebugOptions.PrintGraphFile.getValue(options)) {
|
||||
sharedChannel = createFileChannel(pathProvider);
|
||||
} else {
|
||||
PrintGraphTarget target = DebugOptions.PrintGraph.getValue(options);
|
||||
if (target == PrintGraphTarget.File) {
|
||||
sharedChannel = createFileChannel(pathProvider, null);
|
||||
} else if (target == PrintGraphTarget.Network) {
|
||||
sharedChannel = createNetworkChannel(pathProvider, options);
|
||||
} else {
|
||||
TTY.println("WARNING: Graph dumping requested but value of %s option is %s", DebugOptions.PrintGraph.getName(), PrintGraphTarget.Disable);
|
||||
}
|
||||
}
|
||||
return sharedChannel;
|
||||
@ -88,10 +98,11 @@ final class IgvDumpChannel implements WritableByteChannel {
|
||||
|
||||
private static WritableByteChannel createNetworkChannel(Supplier<Path> pathProvider, OptionValues options) throws IOException {
|
||||
String host = PrintGraphHost.getValue(options);
|
||||
int port = PrintBinaryGraphPort.getValue(options);
|
||||
int port = PrintGraphPort.getValue(options);
|
||||
try {
|
||||
WritableByteChannel channel = SocketChannel.open(new InetSocketAddress(host, port));
|
||||
TTY.println("Connected to the IGV on %s:%d", host, port);
|
||||
String targetAnnouncement = String.format("Connected to the IGV on %s:%d", host, port);
|
||||
maybeAnnounceTarget(targetAnnouncement);
|
||||
return channel;
|
||||
} catch (ClosedByInterruptException | InterruptedIOException e) {
|
||||
/*
|
||||
@ -101,18 +112,39 @@ final class IgvDumpChannel implements WritableByteChannel {
|
||||
*/
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
if (!DebugOptions.PrintGraphFile.hasBeenSet(options)) {
|
||||
return createFileChannel(pathProvider);
|
||||
String networkFailure = String.format("Could not connect to the IGV on %s:%d", host, port);
|
||||
if (pathProvider != null) {
|
||||
return createFileChannel(pathProvider, networkFailure);
|
||||
} else {
|
||||
throw new IOException(String.format("Could not connect to the IGV on %s:%d", host, port), e);
|
||||
throw new IOException(networkFailure, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static WritableByteChannel createFileChannel(Supplier<Path> pathProvider) throws IOException {
|
||||
@NativeImageReinitialize private static String lastTargetAnnouncement;
|
||||
|
||||
private static void maybeAnnounceTarget(String targetAnnouncement) {
|
||||
if (!targetAnnouncement.equals(lastTargetAnnouncement)) {
|
||||
// Ignore races - an extra announcement is ok
|
||||
lastTargetAnnouncement = targetAnnouncement;
|
||||
TTY.println(targetAnnouncement);
|
||||
}
|
||||
}
|
||||
|
||||
private static WritableByteChannel createFileChannel(Supplier<Path> pathProvider, String networkFailure) throws IOException {
|
||||
Path path = pathProvider.get();
|
||||
try {
|
||||
return FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
|
||||
FileChannel channel = FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
|
||||
File dir = path.toFile();
|
||||
if (!dir.isDirectory()) {
|
||||
dir = dir.getParentFile();
|
||||
}
|
||||
if (networkFailure == null) {
|
||||
maybeAnnounceTarget("Dumping IGV graphs in " + dir);
|
||||
} else {
|
||||
maybeAnnounceTarget(networkFailure + ". Dumping IGV graphs in " + dir);
|
||||
}
|
||||
return channel;
|
||||
} catch (IOException e) {
|
||||
throw new IOException(String.format("Failed to open %s to dump IGV graphs", path), e);
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ public class PathUtilities {
|
||||
|
||||
private static final String ELLIPSIS = "...";
|
||||
|
||||
static Path createUnique(OptionValues options, OptionKey<String> baseNameOption, String id, String label, String ext, boolean createDirectory) throws IOException {
|
||||
static Path createUnique(OptionValues options, OptionKey<String> baseNameOption, String id, String label, String ext, boolean createMissingDirectory) throws IOException {
|
||||
String uniqueTag = "";
|
||||
int dumpCounter = 1;
|
||||
String prefix;
|
||||
@ -118,7 +118,7 @@ public class PathUtilities {
|
||||
Path dumpDir = DebugOptions.getDumpDirectory(options);
|
||||
Path result = Paths.get(dumpDir.toString(), fileName);
|
||||
try {
|
||||
if (createDirectory) {
|
||||
if (createMissingDirectory) {
|
||||
return Files.createDirectory(result);
|
||||
} else {
|
||||
try {
|
||||
|
@ -0,0 +1,6 @@
|
||||
Where IdealGraphVisualizer graph dumps triggered by Dump or DumpOnError should be written.
|
||||
The accepted values are:
|
||||
File - Dump IGV graphs to the local file system (see DumpPath).
|
||||
Network - Dump IGV graphs to the network destination specified by PrintGraphHost and PrintGraphPort.
|
||||
If a network connection cannot be opened, dumping falls back to file dumping.
|
||||
Disable - Do not dump IGV graphs.
|
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.graph.test.graphio;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import org.graalvm.graphio.GraphOutput;
|
||||
import org.graalvm.graphio.GraphStructure;
|
||||
import org.junit.Test;
|
||||
|
||||
public final class GraphOutputTest {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("static-method")
|
||||
public void testWritableByteChannel() throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
WritableByteChannel channel = Channels.newChannel(out);
|
||||
ByteBuffer data = generateData(1 << 17);
|
||||
GraphOutput<?, ?> graphOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).embedded(true).build(channel);
|
||||
try (GraphOutput<?, ?> closable = graphOutput) {
|
||||
assertTrue(closable.isOpen());
|
||||
closable.write(data);
|
||||
}
|
||||
assertFalse(graphOutput.isOpen());
|
||||
assertArrayEquals(data.array(), out.toByteArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("static-method")
|
||||
public void testWriteDuringPrint() throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
WritableByteChannel channel = Channels.newChannel(out);
|
||||
class Action implements Runnable {
|
||||
GraphOutput<MockGraph, ?> out;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ByteBuffer data = ByteBuffer.allocate(16);
|
||||
data.limit(16);
|
||||
out.write(data);
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
Action action = new Action();
|
||||
try (GraphOutput<MockGraph, ?> graphOutput = GraphOutput.newBuilder(new MockGraphStructure(action)).protocolVersion(6, 0).build(channel)) {
|
||||
action.out = graphOutput;
|
||||
try {
|
||||
graphOutput.print(new MockGraph(), Collections.emptyMap(), 0, "Mock Graph");
|
||||
fail("Expected IllegalStateException");
|
||||
} catch (IllegalStateException ise) {
|
||||
// expected exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("static-method")
|
||||
public void testEmbeddedWritableByteChannel() throws IOException {
|
||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||
WritableByteChannel expectedChannel = Channels.newChannel(expected);
|
||||
Map<Object, Object> properties = Collections.singletonMap("version.id", 1);
|
||||
try (GraphOutput<MockGraph, ?> graphOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).build(expectedChannel)) {
|
||||
graphOutput.print(new MockGraph(), properties, 1, "Graph 1");
|
||||
graphOutput.write(ByteBuffer.allocate(0));
|
||||
graphOutput.print(new MockGraph(), properties, 2, "Graph 1");
|
||||
}
|
||||
ByteArrayOutputStream embedded = new ByteArrayOutputStream();
|
||||
SharedWritableByteChannel embeddChannel = new SharedWritableByteChannel(Channels.newChannel(embedded));
|
||||
try {
|
||||
try (GraphOutput<MockGraph, ?> baseOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).build(embeddChannel)) {
|
||||
try (GraphOutput<MockGraph, ?> embeddedOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).embedded(true).build((WritableByteChannel) baseOutput)) {
|
||||
embeddedOutput.print(new MockGraph(), properties, 1, "Graph 1");
|
||||
baseOutput.print(new MockGraph(), properties, 2, "Graph 1");
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
embeddChannel.realClose();
|
||||
}
|
||||
assertArrayEquals(expected.toByteArray(), embedded.toByteArray());
|
||||
}
|
||||
|
||||
private static ByteBuffer generateData(int size) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
buffer.put(i, (byte) i);
|
||||
}
|
||||
buffer.limit(size);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private static final class SharedWritableByteChannel implements WritableByteChannel {
|
||||
|
||||
private final WritableByteChannel delegate;
|
||||
|
||||
SharedWritableByteChannel(WritableByteChannel delegate) {
|
||||
Objects.requireNonNull(delegate, "Delegate must be non null.");
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int write(ByteBuffer bb) throws IOException {
|
||||
return delegate.write(bb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen() {
|
||||
return delegate.isOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
}
|
||||
|
||||
void realClose() throws IOException {
|
||||
delegate.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class MockGraphStructure implements GraphStructure<MockGraph, Void, Void, Void> {
|
||||
|
||||
private final Runnable enterAction;
|
||||
|
||||
MockGraphStructure() {
|
||||
this.enterAction = null;
|
||||
}
|
||||
|
||||
MockGraphStructure(Runnable enterAction) {
|
||||
this.enterAction = enterAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockGraph graph(MockGraph currentGraph, Object obj) {
|
||||
onEnter();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Void> nodes(MockGraph graph) {
|
||||
onEnter();
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nodesCount(MockGraph graph) {
|
||||
onEnter();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nodeId(Void node) {
|
||||
onEnter();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean nodeHasPredecessor(Void node) {
|
||||
onEnter();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nodeProperties(MockGraph graph, Void node, Map<String, ? super Object> properties) {
|
||||
onEnter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void node(Object obj) {
|
||||
onEnter();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void nodeClass(Object obj) {
|
||||
onEnter();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void classForNode(Void node) {
|
||||
onEnter();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nameTemplate(Void nodeClass) {
|
||||
onEnter();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nodeClassType(Void nodeClass) {
|
||||
onEnter();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void portInputs(Void nodeClass) {
|
||||
onEnter();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void portOutputs(Void nodeClass) {
|
||||
onEnter();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int portSize(Void port) {
|
||||
onEnter();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean edgeDirect(Void port, int index) {
|
||||
onEnter();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String edgeName(Void port, int index) {
|
||||
onEnter();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object edgeType(Void port, int index) {
|
||||
onEnter();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends Void> edgeNodes(MockGraph graph, Void node, Void port, int index) {
|
||||
onEnter();
|
||||
return null;
|
||||
}
|
||||
|
||||
private void onEnter() {
|
||||
if (enterAction != null) {
|
||||
enterAction.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class MockGraph {
|
||||
}
|
||||
}
|
@ -24,9 +24,7 @@
|
||||
|
||||
package org.graalvm.compiler.graph;
|
||||
|
||||
import static org.graalvm.compiler.core.common.Fields.translateInto;
|
||||
import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere;
|
||||
import static org.graalvm.compiler.graph.Edges.translateInto;
|
||||
import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled;
|
||||
import static org.graalvm.compiler.graph.InputEdges.translateInto;
|
||||
import static org.graalvm.compiler.graph.Node.WithAllEdges;
|
||||
|
@ -36,6 +36,7 @@ import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntr
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicSet;
|
||||
import org.graalvm.compiler.asm.Assembler;
|
||||
import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException;
|
||||
import org.graalvm.compiler.asm.Label;
|
||||
import org.graalvm.compiler.asm.aarch64.AArch64Address;
|
||||
import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
|
||||
@ -47,6 +48,7 @@ import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
|
||||
import org.graalvm.compiler.core.gen.LIRGenerationProvider;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.HotSpotDataBuilder;
|
||||
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
|
||||
@ -86,21 +88,16 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
/**
|
||||
* HotSpot AArch64 specific backend.
|
||||
*/
|
||||
public class AArch64HotSpotBackend extends HotSpotHostBackend {
|
||||
public class AArch64HotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider {
|
||||
|
||||
public AArch64HotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
|
||||
super(config, runtime, providers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
|
||||
private FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
|
||||
RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
|
||||
return new AArch64FrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrameMap newFrameMap(RegisterConfig registerConfig) {
|
||||
return new AArch64FrameMap(getCodeCache(), registerConfig, this);
|
||||
FrameMap frameMap = new AArch64FrameMap(getCodeCache(), registerConfigNonNull, this);
|
||||
return new AArch64FrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -109,8 +106,9 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, Object stub) {
|
||||
return new HotSpotLIRGenerationResult(compilationId, lir, frameMapBuilder, makeCallingConvention(graph, (Stub) stub), stub, config.requiresReservedStackCheck(graph.getMethods()));
|
||||
public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, Object stub) {
|
||||
return new HotSpotLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerConfig), makeCallingConvention(graph, (Stub) stub), stub,
|
||||
config.requiresReservedStackCheck(graph.getMethods()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -218,11 +216,6 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Assembler createAssembler(FrameMap frameMap) {
|
||||
return new AArch64MacroAssembler(getTarget());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
|
||||
HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRen;
|
||||
@ -230,7 +223,7 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend {
|
||||
assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
|
||||
|
||||
Stub stub = gen.getStub();
|
||||
Assembler masm = createAssembler(frameMap);
|
||||
Assembler masm = new AArch64MacroAssembler(getTarget());
|
||||
HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null);
|
||||
|
||||
DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget());
|
||||
@ -252,11 +245,25 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend {
|
||||
|
||||
@Override
|
||||
public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) {
|
||||
Label verifiedStub = new Label();
|
||||
crb.buildLabelOffsets(lir);
|
||||
try {
|
||||
emitCode(crb, lir, installedCodeOwner, verifiedStub);
|
||||
} catch (BranchTargetOutOfBoundsException e) {
|
||||
// A branch estimation was wrong, now retry with conservative label ranges, this
|
||||
// should always work
|
||||
crb.setConservativeLabelRanges();
|
||||
crb.resetForEmittingCode();
|
||||
lir.resetLabels();
|
||||
verifiedStub.reset();
|
||||
emitCode(crb, lir, installedCodeOwner, verifiedStub);
|
||||
}
|
||||
}
|
||||
|
||||
private void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner, Label verifiedStub) {
|
||||
AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm;
|
||||
FrameMap frameMap = crb.frameMap;
|
||||
RegisterConfig regConfig = frameMap.getRegisterConfig();
|
||||
Label verifiedStub = new Label();
|
||||
|
||||
emitCodePrefix(crb, installedCodeOwner, masm, regConfig, verifiedStub);
|
||||
emitCodeBody(crb, lir, masm);
|
||||
emitCodeSuffix(crb, masm, frameMap);
|
||||
|
@ -37,7 +37,7 @@ import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.lir.LIRInstructionClass;
|
||||
import org.graalvm.compiler.lir.Opcode;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
|
||||
import org.graalvm.compiler.serviceprovider.GraalServices;
|
||||
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
|
||||
|
||||
import jdk.vm.ci.code.Register;
|
||||
import jdk.vm.ci.meta.AllocatableValue;
|
||||
@ -71,7 +71,7 @@ public class AArch64HotSpotJumpToExceptionHandlerInCallerOp extends AArch64HotSp
|
||||
public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
|
||||
leaveFrame(crb, masm, /* emitSafepoint */false, false);
|
||||
|
||||
if (GraalServices.JAVA_SPECIFICATION_VERSION < 8) {
|
||||
if (JavaVersionUtil.JAVA_SPECIFICATION_VERSION < 8) {
|
||||
// Restore sp from fp if the exception PC is a method handle call site.
|
||||
try (ScratchRegister sc = masm.getScratchRegister()) {
|
||||
Register scratch = sc.getRegister();
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.hotspot.amd64.test;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.graalvm.compiler.api.test.Graal;
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
import org.graalvm.compiler.runtime.RuntimeProvider;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import jdk.vm.ci.amd64.AMD64;
|
||||
import jdk.vm.ci.code.Architecture;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class BinaryMathStubTest extends GraalCompilerTest {
|
||||
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
public static List<Object[]> data() {
|
||||
ArrayList<Object[]> ret = new ArrayList<>();
|
||||
ret.add(new Object[]{"pow"});
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static final double[] inputs = {0.0D, Math.PI / 2, Math.PI, -1.0D, Double.MAX_VALUE, Double.MIN_VALUE, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY};
|
||||
private final String stub;
|
||||
|
||||
public BinaryMathStubTest(String stub) {
|
||||
this.stub = stub;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void checkAMD64() {
|
||||
Architecture arch = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget().arch;
|
||||
assumeTrue("skipping AMD64 specific test", arch instanceof AMD64);
|
||||
}
|
||||
|
||||
public static double pow(double x, double y) {
|
||||
return Math.pow(x, y);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStub() {
|
||||
for (double x : inputs) {
|
||||
for (double y : inputs) {
|
||||
test(stub, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.hotspot.amd64.test;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.graalvm.compiler.api.test.Graal;
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
import org.graalvm.compiler.runtime.RuntimeProvider;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import jdk.vm.ci.amd64.AMD64;
|
||||
import jdk.vm.ci.code.Architecture;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class UnaryMathStubTest extends GraalCompilerTest {
|
||||
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
public static List<Object[]> data() {
|
||||
ArrayList<Object[]> ret = new ArrayList<>();
|
||||
ret.add(new Object[]{"sin"});
|
||||
ret.add(new Object[]{"cos"});
|
||||
ret.add(new Object[]{"tan"});
|
||||
ret.add(new Object[]{"exp"});
|
||||
ret.add(new Object[]{"log"});
|
||||
ret.add(new Object[]{"log10"});
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static final double[] inputs = {0.0D, Math.PI / 2, Math.PI, -1.0D, Double.MAX_VALUE, Double.MIN_VALUE, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY};
|
||||
private final String stub;
|
||||
|
||||
public UnaryMathStubTest(String stub) {
|
||||
this.stub = stub;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void checkAMD64() {
|
||||
Architecture arch = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget().arch;
|
||||
assumeTrue("skipping AMD64 specific test", arch instanceof AMD64);
|
||||
}
|
||||
|
||||
public static double sin(double value) {
|
||||
return Math.sin(value);
|
||||
}
|
||||
|
||||
public static double cos(double value) {
|
||||
return Math.cos(value);
|
||||
}
|
||||
|
||||
public static double tan(double value) {
|
||||
return Math.tan(value);
|
||||
}
|
||||
|
||||
public static double exp(double value) {
|
||||
return Math.exp(value);
|
||||
}
|
||||
|
||||
public static double log(double value) {
|
||||
return Math.log(value);
|
||||
}
|
||||
|
||||
public static double log10(double value) {
|
||||
return Math.log10(value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStub() {
|
||||
for (double input : inputs) {
|
||||
test(stub, input);
|
||||
}
|
||||
}
|
||||
}
|
@ -199,7 +199,7 @@ public class AMD64HotSpotAddressLowering extends AMD64CompressAddressLowering {
|
||||
CountedLoopInfo countedLoopInfo = loop.counted();
|
||||
IntegerStamp initStamp = (IntegerStamp) inductionVariable.initNode().stamp(NodeView.DEFAULT);
|
||||
if (initStamp.isPositive()) {
|
||||
if (inductionVariable.isConstantExtremum()) {
|
||||
if (inductionVariable.isConstantExtremum() && countedLoopInfo.counterNeverOverflows()) {
|
||||
long init = inductionVariable.constantInit();
|
||||
long stride = inductionVariable.constantStride();
|
||||
long extremum = inductionVariable.constantExtremum();
|
||||
@ -211,7 +211,9 @@ public class AMD64HotSpotAddressLowering extends AMD64CompressAddressLowering {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (countedLoopInfo.getCounter() == inductionVariable && inductionVariable.direction() == InductionVariable.Direction.Up && countedLoopInfo.getOverFlowGuard() != null) {
|
||||
if (countedLoopInfo.getCounter() == inductionVariable &&
|
||||
inductionVariable.direction() == InductionVariable.Direction.Up &&
|
||||
(countedLoopInfo.getOverFlowGuard() != null || countedLoopInfo.counterNeverOverflows())) {
|
||||
return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true));
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ import org.graalvm.compiler.core.amd64.AMD64NodeMatchRules;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
|
||||
import org.graalvm.compiler.core.target.Backend;
|
||||
import org.graalvm.compiler.core.gen.LIRGenerationProvider;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.HotSpotDataBuilder;
|
||||
@ -85,21 +85,16 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
/**
|
||||
* HotSpot AMD64 specific backend.
|
||||
*/
|
||||
public class AMD64HotSpotBackend extends HotSpotHostBackend {
|
||||
public class AMD64HotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider {
|
||||
|
||||
public AMD64HotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
|
||||
super(config, runtime, providers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
|
||||
private FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
|
||||
RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
|
||||
return new AMD64FrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrameMap newFrameMap(RegisterConfig registerConfig) {
|
||||
return new AMD64FrameMap(getCodeCache(), registerConfig, this);
|
||||
FrameMap frameMap = new AMD64FrameMap(getCodeCache(), registerConfigNonNull, this);
|
||||
return new AMD64FrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -108,8 +103,9 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, Object stub) {
|
||||
return new HotSpotLIRGenerationResult(compilationId, lir, frameMapBuilder, makeCallingConvention(graph, (Stub) stub), stub, config.requiresReservedStackCheck(graph.getMethods()));
|
||||
public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, Object stub) {
|
||||
return new HotSpotLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerConfig), makeCallingConvention(graph, (Stub) stub), stub,
|
||||
config.requiresReservedStackCheck(graph.getMethods()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -195,11 +191,6 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Assembler createAssembler(FrameMap frameMap) {
|
||||
return new AMD64MacroAssembler(getTarget());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
|
||||
// Omit the frame if the method:
|
||||
@ -216,7 +207,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend {
|
||||
boolean omitFrame = CanOmitFrame.getValue(options) && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall();
|
||||
|
||||
Stub stub = gen.getStub();
|
||||
Assembler masm = createAssembler(frameMap);
|
||||
Assembler masm = new AMD64MacroAssembler(getTarget());
|
||||
HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame);
|
||||
DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget());
|
||||
CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, debug, compilationResult, Register.None);
|
||||
@ -258,7 +249,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend {
|
||||
/**
|
||||
* Emits the code prior to the verified entry point.
|
||||
*
|
||||
* @param installedCodeOwner see {@link Backend#emitCode}
|
||||
* @param installedCodeOwner see {@link LIRGenerationProvider#emitCode}
|
||||
*/
|
||||
public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, RegisterConfig regConfig, Label verifiedEntry) {
|
||||
HotSpotProviders providers = getProviders();
|
||||
@ -309,14 +300,14 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend {
|
||||
/**
|
||||
* Emits the code which starts at the verified entry point.
|
||||
*
|
||||
* @param installedCodeOwner see {@link Backend#emitCode}
|
||||
* @param installedCodeOwner see {@link LIRGenerationProvider#emitCode}
|
||||
*/
|
||||
public void emitCodeBody(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, LIR lir) {
|
||||
crb.emit(lir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param installedCodeOwner see {@link Backend#emitCode}
|
||||
* @param installedCodeOwner see {@link LIRGenerationProvider#emitCode}
|
||||
*/
|
||||
public void emitCodeSuffix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, FrameMap frameMap) {
|
||||
HotSpotProviders providers = getProviders();
|
||||
|
@ -25,7 +25,6 @@
|
||||
package org.graalvm.compiler.hotspot.amd64;
|
||||
|
||||
import static jdk.vm.ci.common.InitTimer.timer;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -141,7 +140,7 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory {
|
||||
replacements = createReplacements(options, p, snippetReflection, bytecodeProvider);
|
||||
}
|
||||
try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
|
||||
plugins = createGraphBuilderPlugins(compilerConfiguration, config, options, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes);
|
||||
plugins = createGraphBuilderPlugins(compilerConfiguration, config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes);
|
||||
replacements.setGraphBuilderPlugins(plugins);
|
||||
}
|
||||
try (InitTimer rt = timer("create Suites provider")) {
|
||||
@ -157,11 +156,11 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory {
|
||||
}
|
||||
}
|
||||
|
||||
protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, OptionValues options, TargetDescription target,
|
||||
protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, TargetDescription target,
|
||||
HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess,
|
||||
HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) {
|
||||
Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements);
|
||||
AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, GraalArithmeticStubs.getValue(options), false);
|
||||
AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false);
|
||||
return plugins;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall;
|
||||
import static jdk.vm.ci.meta.Value.ILLEGAL;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION;
|
||||
@ -38,10 +39,16 @@ import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.
|
||||
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP;
|
||||
import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
|
||||
import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32;
|
||||
import static org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation.POW;
|
||||
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.COS;
|
||||
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.EXP;
|
||||
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG;
|
||||
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
|
||||
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
|
||||
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
|
||||
import static jdk.internal.vm.compiler.word.LocationIdentity.any;
|
||||
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl;
|
||||
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
|
||||
@ -62,14 +69,6 @@ import jdk.vm.ci.meta.Value;
|
||||
|
||||
public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsProvider {
|
||||
|
||||
public static final ForeignCallDescriptor ARITHMETIC_SIN_STUB = new ForeignCallDescriptor("arithmeticSinStub", double.class, double.class);
|
||||
public static final ForeignCallDescriptor ARITHMETIC_COS_STUB = new ForeignCallDescriptor("arithmeticCosStub", double.class, double.class);
|
||||
public static final ForeignCallDescriptor ARITHMETIC_TAN_STUB = new ForeignCallDescriptor("arithmeticTanStub", double.class, double.class);
|
||||
public static final ForeignCallDescriptor ARITHMETIC_EXP_STUB = new ForeignCallDescriptor("arithmeticExpStub", double.class, double.class);
|
||||
public static final ForeignCallDescriptor ARITHMETIC_POW_STUB = new ForeignCallDescriptor("arithmeticPowStub", double.class, double.class, double.class);
|
||||
public static final ForeignCallDescriptor ARITHMETIC_LOG_STUB = new ForeignCallDescriptor("arithmeticLogStub", double.class, double.class);
|
||||
public static final ForeignCallDescriptor ARITHMETIC_LOG10_STUB = new ForeignCallDescriptor("arithmeticLog10Stub", double.class, double.class);
|
||||
|
||||
private final Value[] nativeABICallerSaveRegisters;
|
||||
|
||||
public AMD64HotSpotForeignCallsProvider(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache,
|
||||
@ -93,14 +92,6 @@ public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro
|
||||
register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any()));
|
||||
register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any()));
|
||||
|
||||
link(new AMD64MathStub(ARITHMETIC_LOG_STUB, options, providers, registerStubCall(ARITHMETIC_LOG_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
|
||||
link(new AMD64MathStub(ARITHMETIC_LOG10_STUB, options, providers, registerStubCall(ARITHMETIC_LOG10_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
|
||||
link(new AMD64MathStub(ARITHMETIC_SIN_STUB, options, providers, registerStubCall(ARITHMETIC_SIN_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
|
||||
link(new AMD64MathStub(ARITHMETIC_COS_STUB, options, providers, registerStubCall(ARITHMETIC_COS_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
|
||||
link(new AMD64MathStub(ARITHMETIC_TAN_STUB, options, providers, registerStubCall(ARITHMETIC_TAN_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
|
||||
link(new AMD64MathStub(ARITHMETIC_EXP_STUB, options, providers, registerStubCall(ARITHMETIC_EXP_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
|
||||
link(new AMD64MathStub(ARITHMETIC_POW_STUB, options, providers, registerStubCall(ARITHMETIC_POW_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
|
||||
|
||||
if (config.useCRC32Intrinsics) {
|
||||
// This stub does callee saving
|
||||
registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
|
||||
@ -138,4 +129,19 @@ public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro
|
||||
return nativeABICallerSaveRegisters;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerMathStubs(GraalHotSpotVMConfig hotSpotVMConfig, HotSpotProviders providers, OptionValues options) {
|
||||
if (GraalArithmeticStubs.getValue(options)) {
|
||||
link(new AMD64MathStub(SIN, options, providers, registerStubCall(SIN.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
|
||||
link(new AMD64MathStub(COS, options, providers, registerStubCall(COS.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
|
||||
link(new AMD64MathStub(TAN, options, providers, registerStubCall(TAN.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
|
||||
link(new AMD64MathStub(EXP, options, providers, registerStubCall(EXP.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
|
||||
link(new AMD64MathStub(LOG, options, providers, registerStubCall(LOG.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
|
||||
link(new AMD64MathStub(LOG10, options, providers, registerStubCall(LOG10.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
|
||||
link(new AMD64MathStub(POW, options, providers, registerStubCall(POW.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
|
||||
} else {
|
||||
super.registerMathStubs(hotSpotVMConfig, providers, options);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,10 +24,10 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.amd64;
|
||||
|
||||
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
|
||||
import static jdk.vm.ci.amd64.AMD64.rbp;
|
||||
import static jdk.vm.ci.amd64.AMD64.rsp;
|
||||
import static jdk.vm.ci.code.ValueUtil.asRegister;
|
||||
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
|
||||
|
||||
import org.graalvm.compiler.asm.amd64.AMD64Address;
|
||||
import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
|
||||
@ -35,7 +35,7 @@ import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
|
||||
import org.graalvm.compiler.lir.LIRInstructionClass;
|
||||
import org.graalvm.compiler.lir.Opcode;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
|
||||
import org.graalvm.compiler.serviceprovider.GraalServices;
|
||||
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
|
||||
|
||||
import jdk.vm.ci.code.Register;
|
||||
import jdk.vm.ci.meta.AllocatableValue;
|
||||
@ -71,7 +71,7 @@ final class AMD64HotSpotJumpToExceptionHandlerInCallerOp extends AMD64HotSpotEpi
|
||||
// Discard the return address, thus completing restoration of caller frame
|
||||
masm.incrementq(rsp, 8);
|
||||
|
||||
if (GraalServices.JAVA_SPECIFICATION_VERSION < 8) {
|
||||
if (JavaVersionUtil.JAVA_SPECIFICATION_VERSION < 8) {
|
||||
// Restore rsp from rbp if the exception PC is a method handle call site.
|
||||
AMD64Address dst = new AMD64Address(thread, isMethodHandleReturnOffset);
|
||||
masm.cmpl(dst, 0);
|
||||
|
@ -118,7 +118,7 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp
|
||||
}
|
||||
|
||||
private AMD64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, BackupSlotProvider backupSlotProvider) {
|
||||
this(new AMD64HotSpotLIRKindTool(), new AMD64ArithmeticLIRGenerator(null, new AMD64HotSpotMaths()), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes);
|
||||
this(new AMD64HotSpotLIRKindTool(), new AMD64ArithmeticLIRGenerator(null), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes);
|
||||
}
|
||||
|
||||
protected AMD64HotSpotLIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config,
|
||||
|
@ -25,15 +25,8 @@
|
||||
package org.graalvm.compiler.hotspot.amd64;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_COS_STUB;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_EXP_STUB;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG10_STUB;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG_STUB;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_POW_STUB;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_SIN_STUB;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_TAN_STUB;
|
||||
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
@ -44,21 +37,26 @@ import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
|
||||
import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode;
|
||||
import org.graalvm.compiler.hotspot.replacements.profiling.ProbabilisticProfileSnippets;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.calc.FloatConvertNode;
|
||||
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
|
||||
import org.graalvm.compiler.nodes.spi.LoweringTool;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.replacements.amd64.AMD64ConvertSnippets;
|
||||
import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation;
|
||||
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
|
||||
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
|
||||
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
|
||||
|
||||
import jdk.vm.ci.code.TargetDescription;
|
||||
import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider {
|
||||
|
||||
private AMD64ConvertSnippets.Templates convertSnippets;
|
||||
private ProbabilisticProfileSnippets.Templates profileSnippets;
|
||||
private AMD64X87MathSnippets.Templates mathSnippets;
|
||||
|
||||
public AMD64HotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers,
|
||||
HotSpotConstantReflectionProvider constantReflection, TargetDescription target) {
|
||||
@ -68,9 +66,10 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider
|
||||
@Override
|
||||
public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, GraalHotSpotVMConfig config) {
|
||||
convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
|
||||
profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options)
|
||||
profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) && !JavaVersionUtil.Java8OrEarlier
|
||||
? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget())
|
||||
: null;
|
||||
mathSnippets = new AMD64X87MathSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
|
||||
super.initialize(options, factories, providers, config);
|
||||
}
|
||||
|
||||
@ -80,47 +79,49 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider
|
||||
convertSnippets.lower((FloatConvertNode) n, tool);
|
||||
} else if (profileSnippets != null && n instanceof ProfileNode) {
|
||||
profileSnippets.lower((ProfileNode) n, tool);
|
||||
} else if (n instanceof UnaryMathIntrinsicNode) {
|
||||
lowerUnaryMath((UnaryMathIntrinsicNode) n, tool);
|
||||
} else {
|
||||
super.lower(n, tool);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ForeignCallDescriptor toForeignCall(UnaryOperation operation) {
|
||||
if (GraalArithmeticStubs.getValue(runtime.getOptions())) {
|
||||
switch (operation) {
|
||||
case LOG:
|
||||
return ARITHMETIC_LOG_STUB;
|
||||
case LOG10:
|
||||
return ARITHMETIC_LOG10_STUB;
|
||||
private void lowerUnaryMath(UnaryMathIntrinsicNode math, LoweringTool tool) {
|
||||
if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) {
|
||||
return;
|
||||
}
|
||||
StructuredGraph graph = math.graph();
|
||||
ResolvedJavaMethod method = graph.method();
|
||||
if (method != null) {
|
||||
if (method.getAnnotation(Snippet.class) != null) {
|
||||
// In the context of SnippetStub, i.e., Graal-generated stubs, use the LIR
|
||||
// lowering to emit the stub assembly code instead of the Node lowering.
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!GraalArithmeticStubs.getValue(graph.getOptions())) {
|
||||
switch (math.getOperation()) {
|
||||
case SIN:
|
||||
return ARITHMETIC_SIN_STUB;
|
||||
case COS:
|
||||
return ARITHMETIC_COS_STUB;
|
||||
case TAN:
|
||||
return ARITHMETIC_TAN_STUB;
|
||||
case EXP:
|
||||
return ARITHMETIC_EXP_STUB;
|
||||
// Math.sin(), .cos() and .tan() guarantee a value within 1 ULP of the exact
|
||||
// result, but x87 trigonometric FPU instructions are only that accurate within
|
||||
// [-pi/4, pi/4]. The snippets fall back to a foreign call to HotSpot stubs
|
||||
// should the inputs outside of that interval.
|
||||
mathSnippets.lower(math, tool);
|
||||
return;
|
||||
case LOG:
|
||||
math.replaceAtUsages(graph.addOrUnique(new AMD64X87MathIntrinsicNode(math.getValue(), UnaryOperation.LOG)));
|
||||
return;
|
||||
case LOG10:
|
||||
math.replaceAtUsages(graph.addOrUnique(new AMD64X87MathIntrinsicNode(math.getValue(), UnaryOperation.LOG10)));
|
||||
return;
|
||||
}
|
||||
} else if (operation == UnaryOperation.EXP) {
|
||||
return operation.foreignCallDescriptor;
|
||||
}
|
||||
// Lower only using LIRGenerator
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ForeignCallDescriptor toForeignCall(BinaryOperation operation) {
|
||||
if (GraalArithmeticStubs.getValue(runtime.getOptions())) {
|
||||
switch (operation) {
|
||||
case POW:
|
||||
return ARITHMETIC_POW_STUB;
|
||||
}
|
||||
} else if (operation == BinaryOperation.POW) {
|
||||
return operation.foreignCallDescriptor;
|
||||
}
|
||||
// Lower only using LIRGenerator
|
||||
return null;
|
||||
ForeignCallNode call = graph.add(new ForeignCallNode(foreignCalls, math.getOperation().foreignCallDescriptor, math.getValue()));
|
||||
graph.addAfterFixed(tool.lastFixedNode(), call);
|
||||
math.replaceAtUsages(call);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.hotspot.amd64;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.COS;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG10;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.SIN;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.TAN;
|
||||
|
||||
import org.graalvm.compiler.core.amd64.AMD64ArithmeticLIRGenerator;
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.hotspot.HotSpotBackend.Options;
|
||||
import org.graalvm.compiler.lir.Variable;
|
||||
import org.graalvm.compiler.lir.gen.LIRGenerator;
|
||||
|
||||
import jdk.vm.ci.meta.Value;
|
||||
|
||||
/**
|
||||
* Lowering of selected {@link Math} routines that depends on the value of
|
||||
* {@link Options#GraalArithmeticStubs}.
|
||||
*/
|
||||
public class AMD64HotSpotMaths implements AMD64ArithmeticLIRGenerator.Maths {
|
||||
|
||||
@Override
|
||||
public Variable emitLog(LIRGenerator gen, Value input, boolean base10) {
|
||||
if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) {
|
||||
return null;
|
||||
}
|
||||
Variable result = gen.newVariable(LIRKind.combine(input));
|
||||
gen.append(new AMD64HotSpotMathIntrinsicOp(base10 ? LOG10 : LOG, result, gen.asAllocatable(input)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variable emitCos(LIRGenerator gen, Value input) {
|
||||
if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) {
|
||||
return null;
|
||||
}
|
||||
Variable result = gen.newVariable(LIRKind.combine(input));
|
||||
gen.append(new AMD64HotSpotMathIntrinsicOp(COS, result, gen.asAllocatable(input)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variable emitSin(LIRGenerator gen, Value input) {
|
||||
if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) {
|
||||
return null;
|
||||
}
|
||||
Variable result = gen.newVariable(LIRKind.combine(input));
|
||||
gen.append(new AMD64HotSpotMathIntrinsicOp(SIN, result, gen.asAllocatable(input)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variable emitTan(LIRGenerator gen, Value input) {
|
||||
if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) {
|
||||
return null;
|
||||
}
|
||||
Variable result = gen.newVariable(LIRKind.combine(input));
|
||||
gen.append(new AMD64HotSpotMathIntrinsicOp(TAN, result, gen.asAllocatable(input)));
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -24,16 +24,8 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.amd64;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_COS_STUB;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_EXP_STUB;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG10_STUB;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG_STUB;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_POW_STUB;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_SIN_STUB;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_TAN_STUB;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
import org.graalvm.compiler.hotspot.stubs.SnippetStub;
|
||||
@ -48,33 +40,38 @@ import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOpera
|
||||
*/
|
||||
public class AMD64MathStub extends SnippetStub {
|
||||
|
||||
public AMD64MathStub(ForeignCallDescriptor descriptor, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
|
||||
super(snippetName(descriptor), options, providers, linkage);
|
||||
public AMD64MathStub(UnaryOperation operation, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
|
||||
super(snippetName(operation), options, providers, linkage);
|
||||
}
|
||||
|
||||
private static String snippetName(ForeignCallDescriptor descriptor) {
|
||||
if (descriptor == ARITHMETIC_LOG_STUB) {
|
||||
return "log";
|
||||
public AMD64MathStub(BinaryOperation operation, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
|
||||
super(snippetName(operation), options, providers, linkage);
|
||||
}
|
||||
|
||||
private static String snippetName(UnaryOperation operation) {
|
||||
switch (operation) {
|
||||
case SIN:
|
||||
return "sin";
|
||||
case COS:
|
||||
return "cos";
|
||||
case TAN:
|
||||
return "tan";
|
||||
case EXP:
|
||||
return "exp";
|
||||
case LOG:
|
||||
return "log";
|
||||
case LOG10:
|
||||
return "log10";
|
||||
default:
|
||||
throw GraalError.shouldNotReachHere("Unknown operation " + operation);
|
||||
}
|
||||
if (descriptor == ARITHMETIC_LOG10_STUB) {
|
||||
return "log10";
|
||||
}
|
||||
if (descriptor == ARITHMETIC_SIN_STUB) {
|
||||
return "sin";
|
||||
}
|
||||
if (descriptor == ARITHMETIC_COS_STUB) {
|
||||
return "cos";
|
||||
}
|
||||
if (descriptor == ARITHMETIC_TAN_STUB) {
|
||||
return "tan";
|
||||
}
|
||||
if (descriptor == ARITHMETIC_EXP_STUB) {
|
||||
return "exp";
|
||||
}
|
||||
if (descriptor == ARITHMETIC_POW_STUB) {
|
||||
}
|
||||
|
||||
private static String snippetName(BinaryOperation operation) {
|
||||
if (operation == BinaryOperation.POW) {
|
||||
return "pow";
|
||||
}
|
||||
throw new InternalError("Unknown operation " + descriptor);
|
||||
throw GraalError.shouldNotReachHere("Unknown operation " + operation);
|
||||
}
|
||||
|
||||
@Snippet
|
||||
|
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2015, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.hotspot.amd64;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.COS;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG10;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.SIN;
|
||||
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.TAN;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
|
||||
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.core.common.type.FloatStamp;
|
||||
import org.graalvm.compiler.core.common.type.PrimitiveStamp;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
|
||||
import org.graalvm.compiler.lir.Variable;
|
||||
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
|
||||
import org.graalvm.compiler.nodeinfo.NodeInfo;
|
||||
import org.graalvm.compiler.nodes.ConstantNode;
|
||||
import org.graalvm.compiler.nodes.NodeView;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.calc.UnaryNode;
|
||||
import org.graalvm.compiler.nodes.spi.LIRLowerable;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
|
||||
|
||||
import jdk.vm.ci.meta.Value;
|
||||
|
||||
@NodeInfo(nameTemplate = "X87MathIntrinsic#{p#operation/s}", cycles = CYCLES_64, size = SIZE_1)
|
||||
public final class AMD64X87MathIntrinsicNode extends UnaryNode implements LIRLowerable {
|
||||
|
||||
public static final NodeClass<AMD64X87MathIntrinsicNode> TYPE = NodeClass.create(AMD64X87MathIntrinsicNode.class);
|
||||
protected final UnaryOperation operation;
|
||||
|
||||
protected AMD64X87MathIntrinsicNode(ValueNode value, UnaryOperation op) {
|
||||
super(TYPE, op.computeStamp(value.stamp(NodeView.DEFAULT)), value);
|
||||
assert value.stamp(NodeView.DEFAULT) instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp(NodeView.DEFAULT)) == 64;
|
||||
this.operation = op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stamp foldStamp(Stamp valueStamp) {
|
||||
return operation.computeStamp(valueStamp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(NodeLIRBuilderTool generator) {
|
||||
LIRGeneratorTool gen = generator.getLIRGeneratorTool();
|
||||
Value input = generator.operand(getValue());
|
||||
Variable result = gen.newVariable(LIRKind.combine(input));
|
||||
|
||||
switch (operation) {
|
||||
case SIN:
|
||||
gen.append(new AMD64HotSpotMathIntrinsicOp(SIN, result, gen.asAllocatable(input)));
|
||||
break;
|
||||
case COS:
|
||||
gen.append(new AMD64HotSpotMathIntrinsicOp(COS, result, gen.asAllocatable(input)));
|
||||
break;
|
||||
case TAN:
|
||||
gen.append(new AMD64HotSpotMathIntrinsicOp(TAN, result, gen.asAllocatable(input)));
|
||||
break;
|
||||
case LOG:
|
||||
gen.append(new AMD64HotSpotMathIntrinsicOp(LOG, result, gen.asAllocatable(input)));
|
||||
break;
|
||||
case LOG10:
|
||||
gen.append(new AMD64HotSpotMathIntrinsicOp(LOG10, result, gen.asAllocatable(input)));
|
||||
break;
|
||||
default:
|
||||
throw GraalError.shouldNotReachHere();
|
||||
}
|
||||
generator.setResult(this, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
|
||||
if (forValue.isConstant()) {
|
||||
return ConstantNode.forDouble(operation.compute(forValue.asJavaConstant().asDouble()));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@NodeIntrinsic
|
||||
public static native double compute(double value, @ConstantNodeParameter UnaryOperation op);
|
||||
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.hotspot.amd64;
|
||||
|
||||
import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
|
||||
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
|
||||
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
|
||||
import org.graalvm.compiler.nodes.spi.LoweringTool;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.phases.util.Providers;
|
||||
import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
|
||||
import org.graalvm.compiler.replacements.SnippetTemplate.Arguments;
|
||||
import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
|
||||
import org.graalvm.compiler.replacements.Snippets;
|
||||
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
|
||||
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
|
||||
|
||||
import jdk.vm.ci.code.TargetDescription;
|
||||
|
||||
public class AMD64X87MathSnippets implements Snippets {
|
||||
|
||||
private static final double PI_4 = Math.PI / 4;
|
||||
|
||||
@Snippet
|
||||
public static double sin(double input) {
|
||||
if (Math.abs(input) < PI_4) {
|
||||
return AMD64X87MathIntrinsicNode.compute(input, UnaryOperation.SIN);
|
||||
}
|
||||
return callDouble1(UnaryOperation.SIN.foreignCallDescriptor, input);
|
||||
}
|
||||
|
||||
@Snippet
|
||||
public static double cos(double input) {
|
||||
if (Math.abs(input) < PI_4) {
|
||||
return AMD64X87MathIntrinsicNode.compute(input, UnaryOperation.COS);
|
||||
}
|
||||
return callDouble1(UnaryOperation.COS.foreignCallDescriptor, input);
|
||||
}
|
||||
|
||||
@Snippet
|
||||
public static double tan(double input) {
|
||||
if (Math.abs(input) < PI_4) {
|
||||
return AMD64X87MathIntrinsicNode.compute(input, UnaryOperation.TAN);
|
||||
}
|
||||
return callDouble1(UnaryOperation.TAN.foreignCallDescriptor, input);
|
||||
}
|
||||
|
||||
@NodeIntrinsic(value = ForeignCallNode.class)
|
||||
private static native double callDouble1(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value);
|
||||
|
||||
public static class Templates extends AbstractTemplates {
|
||||
|
||||
private final SnippetInfo sin;
|
||||
private final SnippetInfo cos;
|
||||
private final SnippetInfo tan;
|
||||
|
||||
public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) {
|
||||
super(options, factories, providers, snippetReflection, target);
|
||||
|
||||
sin = snippet(AMD64X87MathSnippets.class, "sin");
|
||||
cos = snippet(AMD64X87MathSnippets.class, "cos");
|
||||
tan = snippet(AMD64X87MathSnippets.class, "tan");
|
||||
}
|
||||
|
||||
public void lower(UnaryMathIntrinsicNode mathIntrinsicNode, LoweringTool tool) {
|
||||
SnippetInfo info;
|
||||
|
||||
switch (mathIntrinsicNode.getOperation()) {
|
||||
case SIN:
|
||||
info = sin;
|
||||
break;
|
||||
case COS:
|
||||
info = cos;
|
||||
break;
|
||||
case TAN:
|
||||
info = tan;
|
||||
break;
|
||||
default:
|
||||
throw GraalError.shouldNotReachHere("Snippet not found for math intrinsic " + mathIntrinsicNode.getOperation().name());
|
||||
}
|
||||
|
||||
Arguments args = new Arguments(info, mathIntrinsicNode.graph().getGuardsStage(), tool.getLoweringStage());
|
||||
args.add("input", mathIntrinsicNode.getValue());
|
||||
template(mathIntrinsicNode, args).instantiate(providers.getMetaAccess(), mathIntrinsicNode, DEFAULT_REPLACER, tool, args);
|
||||
mathIntrinsicNode.safeDelete();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.hotspot.jdk9.test;
|
||||
|
||||
import static org.junit.Assume.assumeFalse;
|
||||
|
||||
import jdk.vm.ci.code.InstalledCode;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.hotspot.replacements.StringUTF16Substitutions;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.java.NewArrayNode;
|
||||
import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode;
|
||||
import org.graalvm.compiler.replacements.test.MethodSubstitutionTest;
|
||||
import org.graalvm.compiler.test.AddExports;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test substitutions for (innate) methods StringUTF16.toBytes and StringUTF16.getChars provided by
|
||||
* {@link StringUTF16Substitutions}.
|
||||
*/
|
||||
@AddExports({"java.base/java.lang"})
|
||||
public final class StringUTF16ToBytesGetCharsTest extends MethodSubstitutionTest {
|
||||
|
||||
private static final int N = 1000;
|
||||
private static final int N_OVERFLOW = 10;
|
||||
|
||||
@Before
|
||||
public void checkAMD64() {
|
||||
assumeFalse(Java8OrEarlier);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringUTF16ToBytes() throws ClassNotFoundException {
|
||||
Class<?> javaclass = Class.forName("java.lang.StringUTF16");
|
||||
|
||||
ResolvedJavaMethod caller = getResolvedJavaMethod(javaclass, "toBytes", char[].class, int.class, int.class);
|
||||
StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext());
|
||||
assertInGraph(graph, NewArrayNode.class);
|
||||
assertInGraph(graph, ArrayCopyCallNode.class);
|
||||
|
||||
InstalledCode code = getCode(caller, graph);
|
||||
|
||||
for (int srcOffset = 0; srcOffset < 2; srcOffset++) {
|
||||
for (int i = 0; i < N; i++) {
|
||||
int length = i2sz(i);
|
||||
char[] src = fillUTF16Chars(new char[length]);
|
||||
int copiedLength = Math.max(0, length - srcOffset);
|
||||
int srcDelta = Math.min(srcOffset, copiedLength);
|
||||
byte[] dst = (byte[]) invokeSafe(caller, null, src, srcDelta, copiedLength);
|
||||
assert dst.length == copiedLength * 2;
|
||||
byte[] dst2 = (byte[]) executeVarargsSafe(code, src, srcDelta, copiedLength);
|
||||
assertDeepEquals(dst, dst2);
|
||||
}
|
||||
}
|
||||
for (int srcOff = 0; srcOff < N_OVERFLOW; ++srcOff) {
|
||||
for (int len = 0; len < N_OVERFLOW; ++len) {
|
||||
char[] src = fillUTF16Chars(new char[N_OVERFLOW]);
|
||||
test(caller, null, src, srcOff, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringUTF16getChars() throws ClassNotFoundException {
|
||||
Class<?> javaclass = Class.forName("java.lang.StringUTF16");
|
||||
|
||||
ResolvedJavaMethod caller = getResolvedJavaMethod(javaclass, "getChars", byte[].class, int.class, int.class, char[].class, int.class);
|
||||
StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext());
|
||||
assertInGraph(graph, ArrayCopyCallNode.class);
|
||||
|
||||
InstalledCode code = getCode(caller, graph);
|
||||
|
||||
for (int dstOffset = 0; dstOffset < 2; dstOffset++) {
|
||||
for (int srcOffset = 0; srcOffset < 2; srcOffset++) {
|
||||
for (int i = 0; i < N; i++) {
|
||||
int length = i2sz(i);
|
||||
byte[] src = fillUTF16Bytes(new byte[length * 2]);
|
||||
char[] dst = new char[length];
|
||||
int copiedLength = Math.max(0, length - Math.max(dstOffset, srcOffset));
|
||||
int dstDelta = Math.min(dstOffset, copiedLength);
|
||||
int srcDelta = Math.min(srcOffset, copiedLength);
|
||||
invokeSafe(caller, null, src, srcDelta, srcDelta + copiedLength, dst, dstDelta);
|
||||
char[] dst2 = new char[length];
|
||||
executeVarargsSafe(code, src, srcDelta, srcDelta + copiedLength, dst2, dstDelta);
|
||||
assertDeepEquals(dst, dst2);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int srcOff = 0; srcOff < N_OVERFLOW; ++srcOff) {
|
||||
for (int dstOff = 0; dstOff < N_OVERFLOW; ++dstOff) {
|
||||
for (int len = 0; len < N_OVERFLOW; ++len) {
|
||||
byte[] src = fillUTF16Bytes(new byte[N_OVERFLOW]);
|
||||
char[] dst = new char[N_OVERFLOW];
|
||||
test(caller, null, src, srcOff, len, dst, dstOff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static char[] fillUTF16Chars(char[] v) {
|
||||
for (int ch = 0, i = 0; i < v.length; i++, ch += 0x101) {
|
||||
v[i] = (char) ch;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
private static byte[] fillUTF16Bytes(byte[] v) {
|
||||
for (int ch = 1, i = 0; i < v.length; i += 2, ch++) {
|
||||
v[i] = (byte) (ch - 1);
|
||||
v[i + 1] = (byte) ch;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
private static int i2sz(int i) {
|
||||
return i * 3;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2019, 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
|
||||
@ -27,9 +27,12 @@ package org.graalvm.compiler.hotspot.lir.test;
|
||||
import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine;
|
||||
import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
@ -121,6 +124,7 @@ public class BenchmarkCounterOverflowTest extends LIRTest {
|
||||
Assert.assertNotEquals("Expected non-zero exit status", 0, proc.exitCode);
|
||||
|
||||
Iterator<String> it = proc.output.iterator();
|
||||
boolean foundProblematicFrame = false;
|
||||
while (it.hasNext()) {
|
||||
String line = it.next();
|
||||
if (line.contains("Problematic frame:")) {
|
||||
@ -130,11 +134,34 @@ public class BenchmarkCounterOverflowTest extends LIRTest {
|
||||
}
|
||||
line = it.next();
|
||||
if (line.contains(BenchmarkCounterOverflowTest.class.getName() + ".test")) {
|
||||
return;
|
||||
foundProblematicFrame = true;
|
||||
break;
|
||||
}
|
||||
Assert.fail("Unexpected stack trace: " + line);
|
||||
}
|
||||
}
|
||||
Assert.fail(String.format("Could not find method in output:%n%s", proc));
|
||||
// find and delete hserr file
|
||||
while (it.hasNext()) {
|
||||
String line = it.next();
|
||||
if (line.contains("An error report file with more information is saved as:")) {
|
||||
if (!it.hasNext()) {
|
||||
// no more line
|
||||
break;
|
||||
}
|
||||
line = it.next();
|
||||
Pattern pattern = Pattern.compile("^# (.*hs_err_pid.*log)$");
|
||||
Matcher matcher = pattern.matcher(line);
|
||||
if (matcher.matches()) {
|
||||
File hserrFile = new File(matcher.group(1));
|
||||
if (hserrFile.exists()) {
|
||||
if (VERBOSE) {
|
||||
System.out.println("Deleting error report file:" + hserrFile.getAbsolutePath());
|
||||
}
|
||||
hserrFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Assert.assertTrue(String.format("Could not find method in output:%n%s", proc), foundProblematicFrame);
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ import org.graalvm.compiler.code.DataSection.Data;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
|
||||
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
|
||||
import org.graalvm.compiler.core.gen.LIRGenerationProvider;
|
||||
import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules;
|
||||
import org.graalvm.compiler.debug.CounterKey;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
@ -109,7 +110,7 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
/**
|
||||
* HotSpot SPARC specific backend.
|
||||
*/
|
||||
public class SPARCHotSpotBackend extends HotSpotHostBackend {
|
||||
public class SPARCHotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider {
|
||||
|
||||
private static final SizeEstimateStatistics CONSTANT_ESTIMATED_STATS = new SizeEstimateStatistics("ESTIMATE");
|
||||
private static final SizeEstimateStatistics CONSTANT_ACTUAL_STATS = new SizeEstimateStatistics("ACTUAL");
|
||||
@ -134,15 +135,10 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
|
||||
private FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
|
||||
RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
|
||||
return new SPARCFrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrameMap newFrameMap(RegisterConfig registerConfig) {
|
||||
return new SPARCFrameMap(getCodeCache(), registerConfig, this);
|
||||
FrameMap frameMap = new SPARCFrameMap(getCodeCache(), registerConfigNonNull, this);
|
||||
return new SPARCFrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -151,8 +147,9 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, Object stub) {
|
||||
return new HotSpotLIRGenerationResult(compilationId, lir, frameMapBuilder, makeCallingConvention(graph, (Stub) stub), stub, config.requiresReservedStackCheck(graph.getMethods()));
|
||||
public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, Object stub) {
|
||||
return new HotSpotLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerConfig), makeCallingConvention(graph, (Stub) stub), stub,
|
||||
config.requiresReservedStackCheck(graph.getMethods()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -226,11 +223,6 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Assembler createAssembler(FrameMap frameMap) {
|
||||
return new SPARCMacroAssembler(getTarget());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
|
||||
HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRes;
|
||||
@ -238,7 +230,7 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend {
|
||||
assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
|
||||
|
||||
Stub stub = gen.getStub();
|
||||
Assembler masm = createAssembler(frameMap);
|
||||
Assembler masm = new SPARCMacroAssembler(getTarget());
|
||||
// On SPARC we always use stack frames.
|
||||
HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null);
|
||||
DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget());
|
||||
|
@ -24,20 +24,21 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.sparc;
|
||||
|
||||
import static jdk.vm.ci.code.ValueUtil.asRegister;
|
||||
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPR;
|
||||
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.ANNUL;
|
||||
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL;
|
||||
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_NOT_TAKEN;
|
||||
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_TAKEN;
|
||||
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.RCondition.Rc_nz;
|
||||
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.RCondition.Rc_z;
|
||||
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
|
||||
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
|
||||
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
|
||||
import static org.graalvm.compiler.lir.sparc.SPARCMove.loadFromConstantTable;
|
||||
import static jdk.vm.ci.code.ValueUtil.asRegister;
|
||||
|
||||
import org.graalvm.compiler.asm.Label;
|
||||
import org.graalvm.compiler.asm.sparc.SPARCAddress;
|
||||
import org.graalvm.compiler.asm.sparc.SPARCAssembler.CC;
|
||||
import org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag;
|
||||
import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
|
||||
import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister;
|
||||
import org.graalvm.compiler.core.common.CompressEncoding;
|
||||
@ -53,6 +54,7 @@ import jdk.vm.ci.code.ValueUtil;
|
||||
import jdk.vm.ci.hotspot.HotSpotConstant;
|
||||
import jdk.vm.ci.meta.AllocatableValue;
|
||||
import jdk.vm.ci.meta.Constant;
|
||||
import jdk.vm.ci.sparc.SPARC;
|
||||
|
||||
public class SPARCHotSpotMove {
|
||||
|
||||
@ -150,17 +152,33 @@ public class SPARCHotSpotMove {
|
||||
if (encoding.hasBase()) {
|
||||
Register baseReg = asRegister(baseRegister);
|
||||
if (!nonNull) {
|
||||
masm.cmp(inputRegister, baseReg);
|
||||
masm.movcc(ConditionFlag.Equal, CC.Xcc, baseReg, resReg);
|
||||
masm.sub(resReg, baseReg, resReg);
|
||||
Label done = new Label();
|
||||
if (inputRegister.equals(resReg)) {
|
||||
BPR.emit(masm, Rc_nz, ANNUL, PREDICT_TAKEN, inputRegister, done);
|
||||
masm.sub(inputRegister, baseReg, resReg);
|
||||
masm.bind(done);
|
||||
if (encoding.getShift() != 0) {
|
||||
masm.srlx(resReg, encoding.getShift(), resReg);
|
||||
}
|
||||
} else {
|
||||
BPR.emit(masm, Rc_z, NOT_ANNUL, PREDICT_NOT_TAKEN, inputRegister, done);
|
||||
masm.mov(SPARC.g0, resReg);
|
||||
masm.sub(inputRegister, baseReg, resReg);
|
||||
if (encoding.getShift() != 0) {
|
||||
masm.srlx(resReg, encoding.getShift(), resReg);
|
||||
}
|
||||
masm.bind(done);
|
||||
}
|
||||
} else {
|
||||
masm.sub(inputRegister, baseReg, resReg);
|
||||
}
|
||||
if (encoding.getShift() != 0) {
|
||||
masm.srlx(resReg, encoding.getShift(), resReg);
|
||||
if (encoding.getShift() != 0) {
|
||||
masm.srlx(resReg, encoding.getShift(), resReg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
masm.srlx(inputRegister, encoding.getShift(), resReg);
|
||||
if (encoding.getShift() != 0) {
|
||||
masm.srlx(inputRegister, encoding.getShift(), resReg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -196,7 +214,7 @@ public class SPARCHotSpotMove {
|
||||
public static void emitUncompressCode(SPARCMacroAssembler masm, Register inputRegister, Register resReg, Register baseReg, int shift, boolean nonNull) {
|
||||
Register secondaryInput;
|
||||
if (shift != 0) {
|
||||
masm.sll(inputRegister, shift, resReg);
|
||||
masm.sllx(inputRegister, shift, resReg);
|
||||
secondaryInput = resReg;
|
||||
} else {
|
||||
secondaryInput = inputRegister;
|
||||
@ -207,7 +225,7 @@ public class SPARCHotSpotMove {
|
||||
masm.add(secondaryInput, baseReg, resReg);
|
||||
} else {
|
||||
Label done = new Label();
|
||||
BPR.emit(masm, Rc_z, ANNUL, PREDICT_TAKEN, secondaryInput, done);
|
||||
BPR.emit(masm, Rc_nz, ANNUL, PREDICT_TAKEN, secondaryInput, done);
|
||||
masm.add(baseReg, secondaryInput, resReg);
|
||||
masm.bind(done);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2019, 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
|
||||
@ -47,7 +47,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding;
|
||||
import org.graalvm.compiler.runtime.RuntimeProvider;
|
||||
import org.graalvm.compiler.serviceprovider.GraalServices;
|
||||
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
|
||||
import org.graalvm.compiler.test.GraalTest;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -257,7 +257,8 @@ public class CheckGraalIntrinsics extends GraalTest {
|
||||
"java/lang/reflect/Array.newArray(Ljava/lang/Class;I)Ljava/lang/Object;",
|
||||
// HotSpot MacroAssembler-based intrinsic
|
||||
"sun/nio/cs/ISO_8859_1$Encoder.encodeISOArray([CI[BII)I",
|
||||
// Stub based intrinsics but implementation seems complex in C2
|
||||
// We have implemented implCompressMultiBlock0 on JDK9+. Does it worth
|
||||
// backporting as corresponding HotSpot stubs are only generated on SPARC?
|
||||
"sun/security/provider/DigestBase.implCompressMultiBlock([BII)I");
|
||||
|
||||
// See JDK-8207146.
|
||||
@ -271,18 +272,12 @@ public class CheckGraalIntrinsics extends GraalTest {
|
||||
"jdk/jfr/internal/JVM.getClassId(Ljava/lang/Class;)J");
|
||||
|
||||
add(toBeInvestigated,
|
||||
// Some logic and a stub call
|
||||
"com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I",
|
||||
// Stub and very little logic
|
||||
"com/sun/crypto/provider/GHASH.processBlocks([BII[J[J)V",
|
||||
// HotSpot MacroAssembler-based intrinsic
|
||||
"java/lang/Math.fma(DDD)D",
|
||||
// HotSpot MacroAssembler-based intrinsic
|
||||
"java/lang/Math.fma(FFF)F",
|
||||
// Just check if the argument is a compile time constant
|
||||
"java/lang/invoke/MethodHandleImpl.isCompileConstant(Ljava/lang/Object;)Z",
|
||||
// Some logic and a runtime call
|
||||
"java/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I",
|
||||
// Only used as a marker for vectorization?
|
||||
"java/util/stream/Streams$RangeIntSpliterator.forEachRemaining(Ljava/util/function/IntConsumer;)V",
|
||||
// Only implemented on non-AMD64 platforms (some logic and runtime call)
|
||||
@ -295,9 +290,7 @@ public class CheckGraalIntrinsics extends GraalTest {
|
||||
// Control flow, deopts, and a cast
|
||||
"jdk/internal/util/Preconditions.checkIndex(IILjava/util/function/BiFunction;)I",
|
||||
// HotSpot MacroAssembler-based intrinsic
|
||||
"sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray([CI[BII)I",
|
||||
// Runtime call and some complex compiler logic
|
||||
"sun/security/provider/DigestBase.implCompressMultiBlock0([BII)I");
|
||||
"sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray([CI[BII)I");
|
||||
|
||||
/*
|
||||
* Per default, all these operations are mapped to some generic method for which we
|
||||
@ -344,27 +337,45 @@ public class CheckGraalIntrinsics extends GraalTest {
|
||||
// Compact string support - HotSpot MacroAssembler-based intrinsic or complex C2 logic.
|
||||
add(toBeInvestigated,
|
||||
"java/lang/StringCoding.hasNegatives([BII)Z",
|
||||
"java/lang/StringCoding.implEncodeISOArray([BI[BII)I",
|
||||
"java/lang/StringCoding.implEncodeISOArray([BI[BII)I");
|
||||
add(ignore,
|
||||
// handled through an intrinsic for String.equals itself
|
||||
"java/lang/StringLatin1.equals([B[B)Z",
|
||||
|
||||
// handled by an intrinsic for StringLatin1.indexOf([BI[BII)I
|
||||
"java/lang/StringLatin1.indexOf([B[B)I",
|
||||
"java/lang/StringUTF16.getChar([BI)C",
|
||||
"java/lang/StringUTF16.getChars([BII[CI)V",
|
||||
|
||||
// handled through an intrinsic for String.equals itself
|
||||
"java/lang/StringUTF16.equals([B[B)Z",
|
||||
|
||||
// handled by an intrinsic for StringUTF16.indexOfUnsafe
|
||||
"java/lang/StringUTF16.indexOf([BI[BII)I",
|
||||
"java/lang/StringUTF16.indexOf([B[B)I",
|
||||
|
||||
// handled by an intrinsic for StringUTF16.indexOfCharUnsafe
|
||||
"java/lang/StringUTF16.indexOfChar([BIII)I",
|
||||
|
||||
// handled by an intrinsic for StringUTF16.indexOfLatin1Unsafe
|
||||
"java/lang/StringUTF16.indexOfLatin1([BI[BII)I",
|
||||
"java/lang/StringUTF16.indexOfLatin1([B[B)I",
|
||||
"java/lang/StringUTF16.putChar([BII)V",
|
||||
"java/lang/StringUTF16.toBytes([CII)[B");
|
||||
// These are handled through an intrinsic for String.equals itself
|
||||
add(ignore,
|
||||
"java/lang/StringLatin1.equals([B[B)Z",
|
||||
"java/lang/StringUTF16.equals([B[B)Z");
|
||||
"java/lang/StringUTF16.indexOfLatin1([B[B)I");
|
||||
|
||||
if (!config.useAESCTRIntrinsics) {
|
||||
add(ignore,
|
||||
"com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I");
|
||||
}
|
||||
if (!config.useGHASHIntrinsics()) {
|
||||
add(ignore,
|
||||
"com/sun/crypto/provider/GHASH.processBlocks([BII[J[J)V");
|
||||
}
|
||||
if (!(config.useSHA1Intrinsics() || config.useSHA256Intrinsics() || config.useSHA512Intrinsics())) {
|
||||
add(ignore,
|
||||
"sun/security/provider/DigestBase.implCompressMultiBlock0([BII)I");
|
||||
}
|
||||
}
|
||||
|
||||
if (isJDK10OrHigher()) {
|
||||
add(toBeInvestigated,
|
||||
"java/lang/Math.multiplyHigh(JJ)J",
|
||||
"jdk/internal/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I");
|
||||
"java/lang/Math.multiplyHigh(JJ)J");
|
||||
}
|
||||
|
||||
if (isJDK11OrHigher()) {
|
||||
@ -401,10 +412,16 @@ public class CheckGraalIntrinsics extends GraalTest {
|
||||
// Can we implement these on non-AMD64 platforms? C2 seems to.
|
||||
add(toBeInvestigated,
|
||||
"java/lang/String.compareTo(Ljava/lang/String;)I",
|
||||
"java/lang/StringLatin1.indexOf([B[B)I",
|
||||
"java/lang/StringLatin1.inflate([BI[BII)V",
|
||||
"java/lang/StringLatin1.inflate([BI[CII)V",
|
||||
"java/lang/StringUTF16.compress([BI[BII)I",
|
||||
"java/lang/StringUTF16.compress([CI[BII)I",
|
||||
"java/lang/StringUTF16.indexOf([BI[BII)I",
|
||||
"java/lang/StringUTF16.indexOf([B[B)I",
|
||||
"java/lang/StringUTF16.indexOfChar([BIII)I",
|
||||
"java/lang/StringUTF16.indexOfLatin1([BI[BII)I",
|
||||
"java/lang/StringUTF16.indexOfLatin1([B[B)I",
|
||||
"jdk/internal/misc/Unsafe.compareAndExchangeByte(Ljava/lang/Object;JBB)B",
|
||||
"jdk/internal/misc/Unsafe.compareAndExchangeShort(Ljava/lang/Object;JSS)S",
|
||||
"jdk/internal/misc/Unsafe.compareAndSetByte(Ljava/lang/Object;JBB)Z",
|
||||
@ -433,7 +450,9 @@ public class CheckGraalIntrinsics extends GraalTest {
|
||||
"jdk/internal/misc/Unsafe.getAndSet" + oopName + "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;");
|
||||
}
|
||||
add(toBeInvestigated,
|
||||
"com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I",
|
||||
"java/lang/Thread.onSpinWait()V",
|
||||
"java/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I",
|
||||
"jdk/internal/misc/Unsafe.getCharUnaligned(Ljava/lang/Object;J)C",
|
||||
"jdk/internal/misc/Unsafe.getIntUnaligned(Ljava/lang/Object;J)I",
|
||||
"jdk/internal/misc/Unsafe.getLongUnaligned(Ljava/lang/Object;J)J",
|
||||
@ -443,6 +462,10 @@ public class CheckGraalIntrinsics extends GraalTest {
|
||||
"jdk/internal/misc/Unsafe.putLongUnaligned(Ljava/lang/Object;JJ)V",
|
||||
"jdk/internal/misc/Unsafe.putShortUnaligned(Ljava/lang/Object;JS)V");
|
||||
}
|
||||
if (isJDK10OrHigher()) {
|
||||
add(toBeInvestigated,
|
||||
"jdk/internal/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -535,23 +558,23 @@ public class CheckGraalIntrinsics extends GraalTest {
|
||||
}
|
||||
|
||||
private static boolean isJDK9OrHigher() {
|
||||
return GraalServices.JAVA_SPECIFICATION_VERSION >= 9;
|
||||
return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 9;
|
||||
}
|
||||
|
||||
private static boolean isJDK10OrHigher() {
|
||||
return GraalServices.JAVA_SPECIFICATION_VERSION >= 10;
|
||||
return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 10;
|
||||
}
|
||||
|
||||
private static boolean isJDK11OrHigher() {
|
||||
return GraalServices.JAVA_SPECIFICATION_VERSION >= 11;
|
||||
return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 11;
|
||||
}
|
||||
|
||||
private static boolean isJDK12OrHigher() {
|
||||
return GraalServices.JAVA_SPECIFICATION_VERSION >= 12;
|
||||
return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 12;
|
||||
}
|
||||
|
||||
private static boolean isJDK13OrHigher() {
|
||||
return GraalServices.JAVA_SPECIFICATION_VERSION >= 13;
|
||||
return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 13;
|
||||
}
|
||||
|
||||
public interface Refiner {
|
||||
|
@ -31,7 +31,7 @@ import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureA
|
||||
import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries;
|
||||
import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes;
|
||||
import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS;
|
||||
import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
|
||||
import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
@ -90,7 +90,7 @@ import org.graalvm.compiler.options.OptionDescriptors;
|
||||
import org.graalvm.compiler.options.OptionKey;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.options.OptionsParser;
|
||||
import org.graalvm.compiler.serviceprovider.GraalServices;
|
||||
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
|
||||
import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
|
||||
@ -110,7 +110,7 @@ public final class CompileTheWorld {
|
||||
|
||||
/**
|
||||
* Magic token to denote that JDK classes are to be compiled. If
|
||||
* {@link GraalServices#Java8OrEarlier}, then the classes in {@code rt.jar} are compiled.
|
||||
* {@link JavaVersionUtil#Java8OrEarlier}, then the classes in {@code rt.jar} are compiled.
|
||||
* Otherwise the classes in the Java runtime image are compiled.
|
||||
*/
|
||||
public static final String SUN_BOOT_CLASS_PATH = "sun.boot.class.path";
|
||||
|
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, 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.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.hotspot.test;
|
||||
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin;
|
||||
import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
|
||||
import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
|
||||
import org.graalvm.compiler.phases.tiers.HighTierContext;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class EliminateRedundantInitializationPhaseTest extends GraalCompilerTest {
|
||||
@Override
|
||||
protected Plugins getDefaultGraphBuilderPlugins() {
|
||||
Plugins plugins = super.getDefaultGraphBuilderPlugins();
|
||||
plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin());
|
||||
return plugins;
|
||||
}
|
||||
|
||||
public static class X {
|
||||
public static int x;
|
||||
public static int y;
|
||||
public static int z;
|
||||
}
|
||||
|
||||
public static class Y extends X {
|
||||
public static int a;
|
||||
public static int b;
|
||||
}
|
||||
|
||||
public static void assignFields() {
|
||||
X.x = 1;
|
||||
X.y = 2;
|
||||
X.z = 3;
|
||||
}
|
||||
|
||||
public static void assignFieldsConditionally(boolean choice) {
|
||||
X.x = 1;
|
||||
if (choice) {
|
||||
X.y = 2;
|
||||
} else {
|
||||
X.z = 3;
|
||||
}
|
||||
}
|
||||
|
||||
public static void assignFieldsSubclassDominates() {
|
||||
Y.a = 1;
|
||||
X.x = 2;
|
||||
X.y = 3;
|
||||
X.z = 4;
|
||||
}
|
||||
|
||||
public static void assignFieldsConditionallySubclassDominates(boolean choice) {
|
||||
Y.a = 1;
|
||||
if (choice) {
|
||||
X.x = 2;
|
||||
} else {
|
||||
X.y = 3;
|
||||
}
|
||||
Y.z = 4;
|
||||
}
|
||||
|
||||
public static void assignFieldsSubclassPostdominates() {
|
||||
X.x = 1;
|
||||
Y.a = 2;
|
||||
}
|
||||
|
||||
public static void assignFieldsConditionallySubclassPostdominates(boolean choice) {
|
||||
X.x = 1;
|
||||
if (choice) {
|
||||
X.y = 2;
|
||||
} else {
|
||||
X.z = 3;
|
||||
}
|
||||
Y.a = 4;
|
||||
}
|
||||
|
||||
public static void assignFieldsConditionallyMixed(boolean choice) {
|
||||
X.x = 1;
|
||||
if (choice) {
|
||||
Y.a = 2;
|
||||
} else {
|
||||
X.z = 3;
|
||||
}
|
||||
Y.b = 4;
|
||||
}
|
||||
|
||||
public static void assignFieldsInLoop() {
|
||||
X.x = 1;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
X.y += X.z;
|
||||
}
|
||||
}
|
||||
|
||||
public static void assignFieldsInBranches(boolean choice) {
|
||||
if (choice) {
|
||||
X.x = 1;
|
||||
} else {
|
||||
X.y = 2;
|
||||
}
|
||||
X.z = 3;
|
||||
}
|
||||
|
||||
public static void assignFieldsInBranchesMixed(boolean choice) {
|
||||
if (choice) {
|
||||
X.x = 1;
|
||||
} else {
|
||||
Y.a = 2;
|
||||
}
|
||||
X.z = 3;
|
||||
}
|
||||
|
||||
static class SomeClass {
|
||||
@BytecodeParserNeverInline
|
||||
static void method() {
|
||||
}
|
||||
|
||||
@BytecodeParserForceInline
|
||||
static void inlinedMethod() {
|
||||
}
|
||||
}
|
||||
|
||||
public static void invokestatic() {
|
||||
SomeClass.method();
|
||||
}
|
||||
|
||||
public static void invokestaticInlined() {
|
||||
SomeClass.inlinedMethod();
|
||||
}
|
||||
|
||||
private void test(String name, int initNodesAfterParse, int initNodesAfterOpt) {
|
||||
StructuredGraph graph = parseEager(name, AllowAssumptions.NO);
|
||||
Assert.assertEquals(initNodesAfterParse, graph.getNodes().filter(InitializeKlassNode.class).count());
|
||||
HighTierContext highTierContext = getDefaultHighTierContext();
|
||||
new EliminateRedundantInitializationPhase().apply(graph, highTierContext);
|
||||
Assert.assertEquals(initNodesAfterOpt, graph.getNodes().filter(InitializeKlassNode.class).count());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test1() {
|
||||
test("assignFields", 3, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
test("assignFieldsConditionally", 3, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test3() {
|
||||
test("assignFieldsSubclassDominates", 4, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test4() {
|
||||
test("assignFieldsConditionallySubclassDominates", 4, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test5() {
|
||||
test("assignFieldsSubclassPostdominates", 2, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test6() {
|
||||
test("assignFieldsConditionallySubclassPostdominates", 4, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test7() {
|
||||
test("assignFieldsConditionallyMixed", 4, 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test8() {
|
||||
test("assignFieldsInLoop", 4, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test9() {
|
||||
test("assignFieldsInBranches", 3, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test10() {
|
||||
test("assignFieldsInBranchesMixed", 3, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test11() {
|
||||
test("invokestatic", 1, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test12() {
|
||||
test("invokestaticInlined", 1, 1);
|
||||
}
|
||||
}
|
@ -53,6 +53,11 @@ public class GraalOSRTest extends GraalOSRTestBase {
|
||||
testOSR(getInitialOptions(), "testNonReduceLoop");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOSR04() {
|
||||
testOSR(getInitialOptions(), "testDeoptAfterCountedLoop");
|
||||
}
|
||||
|
||||
static int limit = 10000;
|
||||
|
||||
public static int sideEffect;
|
||||
@ -100,4 +105,14 @@ public class GraalOSRTest extends GraalOSRTestBase {
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static ReturnValue testDeoptAfterCountedLoop() {
|
||||
long ret = 0;
|
||||
for (int i = 0; GraalDirectives.injectBranchProbability(1, i < limit * limit); i++) {
|
||||
GraalDirectives.blackhole(i);
|
||||
ret = GraalDirectives.opaque(i);
|
||||
}
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
return ret + 1 == limit * limit ? ReturnValue.SUCCESS : ReturnValue.FAILURE;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.test;
|
||||
|
||||
import static org.graalvm.compiler.debug.DebugOptions.DumpOnError;
|
||||
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
|
||||
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
|
||||
@ -52,6 +53,7 @@ import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.spi.LIRLowerable;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.junit.Test;
|
||||
|
||||
import jdk.vm.ci.code.BytecodeFrame;
|
||||
@ -139,6 +141,14 @@ public class JVMCIInfopointErrorTest extends GraalCompilerTest {
|
||||
test(getDebugContext(), spec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoids dumping during tests which are expected to fail.
|
||||
*/
|
||||
private void testNoDump(TestSpec spec) {
|
||||
OptionValues options = new OptionValues(getInitialOptions(), DumpOnError, false);
|
||||
test(getDebugContext(options, null, null), spec);
|
||||
}
|
||||
|
||||
private void test(DebugContext debug, TestSpec spec) {
|
||||
ResolvedJavaMethod method = getResolvedJavaMethod("testMethod");
|
||||
|
||||
@ -154,7 +164,7 @@ public class JVMCIInfopointErrorTest extends GraalCompilerTest {
|
||||
|
||||
@Test(expected = Error.class)
|
||||
public void testInvalidShortOop() {
|
||||
test((tool, state, safepoint) -> {
|
||||
testNoDump((tool, state, safepoint) -> {
|
||||
PlatformKind kind = tool.target().arch.getPlatformKind(JavaKind.Short);
|
||||
LIRKind lirKind = LIRKind.reference(kind);
|
||||
|
||||
@ -167,7 +177,7 @@ public class JVMCIInfopointErrorTest extends GraalCompilerTest {
|
||||
|
||||
@Test(expected = Error.class)
|
||||
public void testInvalidShortDerivedOop() {
|
||||
test((tool, state, safepoint) -> {
|
||||
testNoDump((tool, state, safepoint) -> {
|
||||
Variable baseOop = tool.newVariable(LIRKind.fromJavaKind(tool.target().arch, JavaKind.Object));
|
||||
tool.append(new ValueDef(baseOop));
|
||||
|
||||
|
@ -37,6 +37,7 @@ import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
import org.graalvm.compiler.debug.DebugOptions.PrintGraphTarget;
|
||||
import org.graalvm.compiler.test.SubprocessUtil;
|
||||
import org.graalvm.compiler.test.SubprocessUtil.Subprocess;
|
||||
import org.junit.Assert;
|
||||
@ -54,12 +55,12 @@ public class OptionsInFileTest extends GraalCompilerTest {
|
||||
try {
|
||||
Assert.assertFalse(methodFilterValue.equals(MethodFilter.getDefaultValue()));
|
||||
Assert.assertFalse(debugFilterValue.equals(Dump.getDefaultValue()));
|
||||
Assert.assertTrue(PrintGraph.getDefaultValue());
|
||||
Assert.assertEquals(PrintGraphTarget.File, PrintGraph.getDefaultValue());
|
||||
|
||||
try (PrintStream out = new PrintStream(new FileOutputStream(optionsFile))) {
|
||||
out.println(MethodFilter.getName() + "=" + methodFilterValue);
|
||||
out.println(Dump.getName() + "=" + debugFilterValue);
|
||||
out.println(PrintGraph.getName() + " = false");
|
||||
out.println(PrintGraph.getName() + " = Network");
|
||||
}
|
||||
|
||||
List<String> vmArgs = withoutDebuggerArguments(getVMCommandLine());
|
||||
@ -70,7 +71,7 @@ public class OptionsInFileTest extends GraalCompilerTest {
|
||||
String[] expected = {
|
||||
"graal.MethodFilter := \"a very unlikely method name\"",
|
||||
"graal.Dump := \"a very unlikely debug scope\"",
|
||||
"graal.PrintGraph := false"};
|
||||
"graal.PrintGraph := Network"};
|
||||
for (String line : proc.output) {
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
if (expected[i] != null && line.contains(expected[i])) {
|
||||
|
@ -73,6 +73,10 @@ public class ReservedStackAccessTest extends HotSpotGraalCompilerTest {
|
||||
vmArgs.add("-XX:+UseJVMCICompiler");
|
||||
vmArgs.add("-Dgraal.Inline=false");
|
||||
vmArgs.add("-XX:CompileCommand=exclude,java/util/concurrent/locks/AbstractOwnableSynchronizer.setExclusiveOwnerThread");
|
||||
|
||||
// Avoid SOE in HotSpotJVMCIRuntime.adjustCompilationLevel
|
||||
vmArgs.add("-Dgraal.CompileGraalWithC1Only=false");
|
||||
|
||||
Subprocess proc = SubprocessUtil.java(vmArgs, ReservedStackAccessTest.class.getName());
|
||||
boolean passed = false;
|
||||
for (String line : proc.output) {
|
||||
@ -81,9 +85,7 @@ public class ReservedStackAccessTest extends HotSpotGraalCompilerTest {
|
||||
}
|
||||
}
|
||||
if (!passed) {
|
||||
for (String line : proc.output) {
|
||||
System.err.println("" + line);
|
||||
}
|
||||
System.err.println(proc);
|
||||
}
|
||||
assertTrue(passed);
|
||||
}
|
||||
|
@ -32,10 +32,10 @@ import org.graalvm.compiler.api.replacements.Fold;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier;
|
||||
import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.gc.g1.G1PreWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.gc.g1.G1ReferentFieldReadBarrier;
|
||||
import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
|
||||
|
@ -32,12 +32,12 @@ import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Scope;
|
||||
import org.graalvm.compiler.debug.DebugDumpScope;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.gc.g1.G1ArrayRangePostWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.gc.g1.G1ArrayRangePreWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.gc.g1.G1PreWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.gc.shared.SerialArrayRangeWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier;
|
||||
import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
|
||||
import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase;
|
||||
import org.graalvm.compiler.nodes.AbstractBeginNode;
|
||||
|
@ -368,8 +368,14 @@ public class CompilationTask {
|
||||
installedCode = null;
|
||||
Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult};
|
||||
try (DebugContext.Scope s = debug.scope("CodeInstall", context)) {
|
||||
installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug, getRequest().getMethod(), getRequest(), compResult,
|
||||
getRequest().getMethod().getSpeculationLog(), null, installAsDefault, context);
|
||||
HotSpotCompilationRequest request = getRequest();
|
||||
installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug,
|
||||
request.getMethod(),
|
||||
request,
|
||||
compResult,
|
||||
null,
|
||||
installAsDefault,
|
||||
context);
|
||||
} catch (Throwable e) {
|
||||
throw debug.handle(e);
|
||||
}
|
||||
|
@ -92,6 +92,7 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
|
||||
public final boolean useBiasedLocking = getFlag("UseBiasedLocking", Boolean.class);
|
||||
public final boolean usePopCountInstruction = getFlag("UsePopCountInstruction", Boolean.class);
|
||||
public final boolean useAESIntrinsics = getFlag("UseAESIntrinsics", Boolean.class);
|
||||
public final boolean useAESCTRIntrinsics = getFlag("UseAESCTRIntrinsics", Boolean.class, false);
|
||||
public final boolean useCRC32Intrinsics = getFlag("UseCRC32Intrinsics", Boolean.class);
|
||||
public final boolean useCRC32CIntrinsics = versioned.useCRC32CIntrinsics;
|
||||
public final boolean threadLocalHandshakes = getFlag("ThreadLocalHandshakes", Boolean.class, false);
|
||||
@ -100,10 +101,12 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
|
||||
private final boolean useSHA1Intrinsics = getFlag("UseSHA1Intrinsics", Boolean.class);
|
||||
private final boolean useSHA256Intrinsics = getFlag("UseSHA256Intrinsics", Boolean.class);
|
||||
private final boolean useSHA512Intrinsics = getFlag("UseSHA512Intrinsics", Boolean.class);
|
||||
private final boolean useGHASHIntrinsics = getFlag("UseGHASHIntrinsics", Boolean.class, false);
|
||||
private final boolean useMontgomeryMultiplyIntrinsic = getFlag("UseMontgomeryMultiplyIntrinsic", Boolean.class, false);
|
||||
private final boolean useMontgomerySquareIntrinsic = getFlag("UseMontgomerySquareIntrinsic", Boolean.class, false);
|
||||
private final boolean useMulAddIntrinsic = getFlag("UseMulAddIntrinsic", Boolean.class, false);
|
||||
private final boolean useSquareToLenIntrinsic = getFlag("UseSquareToLenIntrinsic", Boolean.class, false);
|
||||
public final boolean useVectorizedMismatchIntrinsic = getFlag("UseVectorizedMismatchIntrinsic", Boolean.class, false);
|
||||
|
||||
/*
|
||||
* These are methods because in some JDKs the flags are visible but the stubs themselves haven't
|
||||
@ -114,15 +117,19 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
|
||||
}
|
||||
|
||||
public boolean useSHA1Intrinsics() {
|
||||
return useSHA1Intrinsics && sha1ImplCompress != 0;
|
||||
return useSHA1Intrinsics && sha1ImplCompress != 0 && sha1ImplCompressMultiBlock != 0;
|
||||
}
|
||||
|
||||
public boolean useSHA256Intrinsics() {
|
||||
return useSHA256Intrinsics && sha256ImplCompress != 0;
|
||||
return useSHA256Intrinsics && sha256ImplCompress != 0 && sha256ImplCompressMultiBlock != 0;
|
||||
}
|
||||
|
||||
public boolean useSHA512Intrinsics() {
|
||||
return useSHA512Intrinsics && sha512ImplCompress != 0;
|
||||
return useSHA512Intrinsics && sha512ImplCompress != 0 && sha512ImplCompressMultiBlock != 0;
|
||||
}
|
||||
|
||||
public boolean useGHASHIntrinsics() {
|
||||
return useGHASHIntrinsics && ghashProcessBlocks != 0;
|
||||
}
|
||||
|
||||
public boolean useMontgomeryMultiplyIntrinsic() {
|
||||
@ -309,7 +316,17 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
|
||||
public final int jvmAccWrittenFlags = getConstant("JVM_ACC_WRITTEN_FLAGS", Integer.class);
|
||||
public final int jvmAccSynthetic = getConstant("JVM_ACC_SYNTHETIC", Integer.class);
|
||||
|
||||
public final int jvmciCompileStateCanPostOnExceptionsOffset = getFieldOffset("JVMCIEnv::_jvmti_can_post_on_exceptions", Integer.class, "jbyte", Integer.MIN_VALUE);
|
||||
public final int jvmciCompileStateCanPostOnExceptionsOffset = getJvmciCompileStateCanPostOnExceptionsOffset();
|
||||
|
||||
// Integer.MIN_VALUE if not available
|
||||
private int getJvmciCompileStateCanPostOnExceptionsOffset() {
|
||||
int offset = getFieldOffset("JVMCICompileState::_jvmti_can_post_on_exceptions", Integer.class, "jbyte", Integer.MIN_VALUE);
|
||||
if (offset == Integer.MIN_VALUE) {
|
||||
// JDK 12
|
||||
offset = getFieldOffset("JVMCIEnv::_jvmti_can_post_on_exceptions", Integer.class, "jbyte", Integer.MIN_VALUE);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
public final int threadTlabOffset = getFieldOffset("Thread::_tlab", Integer.class, "ThreadLocalAllocBuffer");
|
||||
public final int javaThreadAnchorOffset = getFieldOffset("JavaThread::_anchor", Integer.class, "JavaFrameAnchor");
|
||||
@ -372,12 +389,29 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
|
||||
public final int pendingExceptionOffset = getFieldOffset("ThreadShadow::_pending_exception", Integer.class, "oop");
|
||||
|
||||
public final int pendingDeoptimizationOffset = getFieldOffset("JavaThread::_pending_deoptimization", Integer.class, "int");
|
||||
public final int pendingFailedSpeculationOffset = getFieldOffset("JavaThread::_pending_failed_speculation", Integer.class, "long");
|
||||
public final int pendingTransferToInterpreterOffset = getFieldOffset("JavaThread::_pending_transfer_to_interpreter", Integer.class, "bool");
|
||||
|
||||
private final int javaFrameAnchorLastJavaSpOffset = getFieldOffset("JavaFrameAnchor::_last_Java_sp", Integer.class, "intptr_t*");
|
||||
private final int javaFrameAnchorLastJavaPcOffset = getFieldOffset("JavaFrameAnchor::_last_Java_pc", Integer.class, "address");
|
||||
|
||||
public final int pendingFailedSpeculationOffset;
|
||||
{
|
||||
String name = "JavaThread::_pending_failed_speculation";
|
||||
int offset = -1;
|
||||
try {
|
||||
offset = getFieldOffset(name, Integer.class, "jlong");
|
||||
} catch (JVMCIError e) {
|
||||
try {
|
||||
offset = getFieldOffset(name, Integer.class, "long");
|
||||
} catch (JVMCIError e2) {
|
||||
}
|
||||
}
|
||||
if (offset == -1) {
|
||||
throw new JVMCIError("cannot get offset of field " + name + " with type long or jlong");
|
||||
}
|
||||
pendingFailedSpeculationOffset = offset;
|
||||
}
|
||||
|
||||
public int threadLastJavaSpOffset() {
|
||||
return javaThreadAnchorOffset + javaFrameAnchorLastJavaSpOffset;
|
||||
}
|
||||
@ -602,11 +636,11 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
|
||||
public final long crcTableAddress = getFieldValue("StubRoutines::_crc_table_adr", Long.class, "address");
|
||||
|
||||
public final long sha1ImplCompress = getFieldValue("StubRoutines::_sha1_implCompress", Long.class, "address", 0L);
|
||||
public final long sha1ImplCompressMB = getFieldValue("StubRoutines::_sha1_implCompressMB", Long.class, "address", 0L);
|
||||
public final long sha1ImplCompressMultiBlock = getFieldValue("StubRoutines::_sha1_implCompressMB", Long.class, "address", 0L);
|
||||
public final long sha256ImplCompress = getFieldValue("StubRoutines::_sha256_implCompress", Long.class, "address", 0L);
|
||||
public final long sha256ImplCompressMB = getFieldValue("StubRoutines::_sha256_implCompressMB", Long.class, "address", 0L);
|
||||
public final long sha256ImplCompressMultiBlock = getFieldValue("StubRoutines::_sha256_implCompressMB", Long.class, "address", 0L);
|
||||
public final long sha512ImplCompress = getFieldValue("StubRoutines::_sha512_implCompress", Long.class, "address", 0L);
|
||||
public final long sha512ImplCompressMB = getFieldValue("StubRoutines::_sha512_implCompressMB", Long.class, "address", 0L);
|
||||
public final long sha512ImplCompressMultiBlock = getFieldValue("StubRoutines::_sha512_implCompressMB", Long.class, "address", 0L);
|
||||
public final long multiplyToLen = getFieldValue("StubRoutines::_multiplyToLen", Long.class, "address", longRequiredOnAMD64);
|
||||
|
||||
public final long counterModeAESCrypt = getFieldValue("StubRoutines::_counterMode_AESCrypt", Long.class, "address", 0L);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2019, 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
|
||||
@ -46,6 +46,7 @@ import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantStubCall;
|
||||
import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions;
|
||||
import org.graalvm.compiler.hotspot.replacements.BigIntegerSubstitutions;
|
||||
import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions;
|
||||
import org.graalvm.compiler.hotspot.replacements.DigestBaseSubstitutions;
|
||||
import org.graalvm.compiler.hotspot.replacements.SHA2Substitutions;
|
||||
import org.graalvm.compiler.hotspot.replacements.SHA5Substitutions;
|
||||
import org.graalvm.compiler.hotspot.replacements.SHASubstitutions;
|
||||
@ -71,6 +72,7 @@ import org.graalvm.compiler.options.OptionKey;
|
||||
import org.graalvm.compiler.options.OptionType;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.phases.tiers.SuitesProvider;
|
||||
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
|
||||
import org.graalvm.compiler.word.Word;
|
||||
import jdk.internal.vm.compiler.word.Pointer;
|
||||
|
||||
@ -95,7 +97,7 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen
|
||||
public static class Options {
|
||||
// @formatter:off
|
||||
@Option(help = "Use Graal arithmetic stubs instead of HotSpot stubs where possible")
|
||||
public static final OptionKey<Boolean> GraalArithmeticStubs = new OptionKey<>(false); // GR-8276
|
||||
public static final OptionKey<Boolean> GraalArithmeticStubs = new OptionKey<>(JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 9);
|
||||
@Option(help = "Enables instruction profiling on assembler level. Valid values are a comma separated list of supported instructions." +
|
||||
" Compare with subclasses of Assembler.InstructionCounter.", type = OptionType.Debug)
|
||||
public static final OptionKey<String> ASMInstructionProfiling = new OptionKey<>(null);
|
||||
@ -261,6 +263,36 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen
|
||||
@NodeIntrinsic(ForeignCallNode.class)
|
||||
private static native void sha5ImplCompressStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state);
|
||||
|
||||
/**
|
||||
* @see DigestBaseSubstitutions#implCompressMultiBlock0
|
||||
*/
|
||||
public static final ForeignCallDescriptor SHA_IMPL_COMPRESS_MB = new ForeignCallDescriptor("shaImplCompressMB", int.class, Word.class, Object.class, int.class, int.class);
|
||||
|
||||
public static int shaImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) {
|
||||
return shaImplCompressMBStub(HotSpotBackend.SHA_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit);
|
||||
}
|
||||
|
||||
@NodeIntrinsic(ForeignCallNode.class)
|
||||
private static native int shaImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit);
|
||||
|
||||
public static final ForeignCallDescriptor SHA2_IMPL_COMPRESS_MB = new ForeignCallDescriptor("sha2ImplCompressMB", int.class, Word.class, Object.class, int.class, int.class);
|
||||
|
||||
public static int sha2ImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) {
|
||||
return sha2ImplCompressMBStub(HotSpotBackend.SHA2_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit);
|
||||
}
|
||||
|
||||
@NodeIntrinsic(ForeignCallNode.class)
|
||||
private static native int sha2ImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit);
|
||||
|
||||
public static final ForeignCallDescriptor SHA5_IMPL_COMPRESS_MB = new ForeignCallDescriptor("sha5ImplCompressMB", int.class, Word.class, Object.class, int.class, int.class);
|
||||
|
||||
public static int sha5ImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) {
|
||||
return sha5ImplCompressMBStub(HotSpotBackend.SHA5_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit);
|
||||
}
|
||||
|
||||
@NodeIntrinsic(ForeignCallNode.class)
|
||||
private static native int sha5ImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit);
|
||||
|
||||
public static void unsafeArraycopy(Word srcAddr, Word dstAddr, Word size) {
|
||||
unsafeArraycopyStub(UNSAFE_ARRAYCOPY, srcAddr, dstAddr, size);
|
||||
}
|
||||
@ -268,6 +300,37 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen
|
||||
@NodeIntrinsic(ForeignCallNode.class)
|
||||
private static native void unsafeArraycopyStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word srcAddr, Word dstAddr, Word size);
|
||||
|
||||
/**
|
||||
* Descriptor for {@code StubRoutines::_ghash_processBlocks}.
|
||||
*/
|
||||
public static final ForeignCallDescriptor GHASH_PROCESS_BLOCKS = new ForeignCallDescriptor("ghashProcessBlocks", void.class, Word.class, Word.class, Word.class, int.class);
|
||||
|
||||
/**
|
||||
* Descriptor for {@code StubRoutines::_counterMode_AESCrypt}.
|
||||
*/
|
||||
public static final ForeignCallDescriptor COUNTERMODE_IMPL_CRYPT = new ForeignCallDescriptor("counterModeAESCrypt", int.class, Word.class, Word.class, Word.class, Word.class, int.class,
|
||||
Word.class, Word.class);
|
||||
|
||||
public static int counterModeAESCrypt(Word srcAddr, Word dstAddr, Word kPtr, Word cntPtr, int len, Word encCntPtr, Word used) {
|
||||
return counterModeAESCrypt(COUNTERMODE_IMPL_CRYPT, srcAddr, dstAddr, kPtr, cntPtr, len, encCntPtr, used);
|
||||
}
|
||||
|
||||
@NodeIntrinsic(ForeignCallNode.class)
|
||||
private static native int counterModeAESCrypt(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word srcAddr, Word dstAddr, Word kPtr, Word cntPtr, int len, Word encCntPtr,
|
||||
Word used);
|
||||
|
||||
/**
|
||||
* Descriptor for {@code StubRoutines::_vectorizedMismatch}.
|
||||
*/
|
||||
public static final ForeignCallDescriptor VECTORIZED_MISMATCHED = new ForeignCallDescriptor("vectorizedMismatch", int.class, Word.class, Word.class, int.class, int.class);
|
||||
|
||||
public static int vectorizedMismatch(Word aAddr, Word bAddr, int length, int log2ArrayIndexScale) {
|
||||
return vectorizedMismatchStub(VECTORIZED_MISMATCHED, aAddr, bAddr, length, log2ArrayIndexScale);
|
||||
}
|
||||
|
||||
@NodeIntrinsic(ForeignCallNode.class)
|
||||
private static native int vectorizedMismatchStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word aAddr, Word bAddr, int length, int log2ArrayIndexScale);
|
||||
|
||||
/**
|
||||
* @see VMErrorNode
|
||||
*/
|
||||
@ -388,6 +451,13 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen
|
||||
return translateToCallerRegisters(destroyedRegisters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates a set of registers from the callee's perspective to the caller's perspective. This
|
||||
* is needed for architectures where input/output registers are renamed during a call (e.g.
|
||||
* register windows on SPARC). Registers which are not visible by the caller are removed.
|
||||
*/
|
||||
protected abstract EconomicSet<Register> translateToCallerRegisters(EconomicSet<Register> calleeRegisters);
|
||||
|
||||
/**
|
||||
* Updates a given stub with respect to the registers it destroys.
|
||||
* <p>
|
||||
|
@ -88,7 +88,7 @@ public class HotSpotCompiledCodeBuilder {
|
||||
|
||||
ResolvedJavaMethod[] methods = compResult.getMethods();
|
||||
|
||||
List<CodeAnnotation> annotations = compResult.getAnnotations();
|
||||
List<CodeAnnotation> annotations = compResult.getCodeAnnotations();
|
||||
Comment[] comments = new Comment[annotations.size()];
|
||||
if (!annotations.isEmpty()) {
|
||||
for (int i = 0; i < comments.length; i++) {
|
||||
@ -129,16 +129,16 @@ public class HotSpotCompiledCodeBuilder {
|
||||
boolean hasUnsafeAccess = compResult.hasUnsafeAccess();
|
||||
|
||||
int id;
|
||||
long jvmciEnv;
|
||||
long jvmciCompileState;
|
||||
if (compRequest != null) {
|
||||
id = compRequest.getId();
|
||||
jvmciEnv = compRequest.getJvmciEnv();
|
||||
jvmciCompileState = compRequest.getJvmciEnv();
|
||||
} else {
|
||||
id = hsMethod.allocateCompileId(entryBCI);
|
||||
jvmciEnv = 0L;
|
||||
jvmciCompileState = 0L;
|
||||
}
|
||||
return new HotSpotCompiledNmethod(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC,
|
||||
totalFrameSize, customStackArea, hsMethod, entryBCI, id, jvmciEnv, hasUnsafeAccess);
|
||||
totalFrameSize, customStackArea, hsMethod, entryBCI, id, jvmciCompileState, hasUnsafeAccess);
|
||||
} else {
|
||||
return new HotSpotCompiledCode(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC,
|
||||
totalFrameSize, customStackArea);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user