--- a/make/CompileJavaModules.gmk Tue Mar 12 12:12:01 2019 -0700
+++ b/make/CompileJavaModules.gmk Tue Mar 12 19:17:42 2019 +0100
@@ -461,6 +461,7 @@
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 \
--- a/make/test/JtregGraalUnit.gmk Tue Mar 12 12:12:01 2019 -0700
+++ b/make/test/JtregGraalUnit.gmk Tue Mar 12 19:17:42 2019 +0100
@@ -92,6 +92,7 @@
$(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 \
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java Tue Mar 12 19:17:42 2019 +0100
@@ -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.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 @@
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 @@
}
/**
- * 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 @@
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"),
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java Tue Mar 12 19:17:42 2019 +0100
@@ -166,7 +166,7 @@
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);
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java Tue Mar 12 19:17:42 2019 +0100
@@ -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 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 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));
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java Tue Mar 12 19:17:42 2019 +0100
@@ -880,15 +880,15 @@
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 @@
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 {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java Tue Mar 12 19:17:42 2019 +0100
@@ -33,6 +33,9 @@
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 @@
*
* @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 @@
*
* @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 @@
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);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Tue Mar 12 19:17:42 2019 +0100
@@ -683,7 +683,7 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64BaseAssembler.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64BaseAssembler.java Tue Mar 12 19:17:42 2019 +0100
@@ -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 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 @@
}
}
- /**
- * 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 @@
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()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java Tue Mar 12 19:17:42 2019 +0100
@@ -136,9 +136,9 @@
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 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);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java Tue Mar 12 19:17:42 2019 +0100
@@ -32,6 +32,7 @@
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 @@
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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/BranchTargetOutOfBoundsException.java Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,44 @@
+/*
+ * 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.asm;
+
+import org.graalvm.compiler.core.common.GraalBailoutException;
+
+@SuppressWarnings("serial")
+public class BranchTargetOutOfBoundsException extends GraalBailoutException {
+
+ public BranchTargetOutOfBoundsException(boolean permanent, String format, Object... args) {
+ super(permanent, format, args);
+ }
+
+ public BranchTargetOutOfBoundsException(String format, Object... args) {
+ super(format, args);
+ }
+
+ public BranchTargetOutOfBoundsException(Throwable cause, String format, Object... args) {
+ super(cause, format, args);
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java Tue Mar 12 19:17:42 2019 +0100
@@ -55,6 +55,7 @@
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
@@ -221,6 +222,11 @@
private ResolvedJavaMethod[] methods;
/**
+ * The {@link SpeculationLog} log used during compilation.
+ */
+ private SpeculationLog speculationLog;
+
+ /**
* The list of fields that were accessed from the bytecodes.
*/
private ResolvedJavaField[] fields;
@@ -373,6 +379,21 @@
}
/**
+ * 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 @@
/**
* @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 @@
* 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 void clearInfopoints() {
+ infopoints.clear();
+ }
+
+ public void clearExceptionHandlers() {
+ exceptionHandlers.clear();
+ }
+
private void checkOpen() {
if (closed) {
throw new IllegalStateException();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/HexCodeFileDisassemblerProvider.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/HexCodeFileDisassemblerProvider.java Tue Mar 12 19:17:42 2019 +0100
@@ -78,7 +78,7 @@
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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64CbzTest.java Tue Mar 12 19:17:42 2019 +0100
@@ -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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64MembarOpTest.java Tue Mar 12 19:17:42 2019 +0100
@@ -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);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64TestBitAndBranchTest.java Tue Mar 12 19:17:42 2019 +0100
@@ -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);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java Tue Mar 12 19:17:42 2019 +0100
@@ -485,26 +485,6 @@
}
@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();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java Tue Mar 12 19:17:42 2019 +0100
@@ -52,6 +52,7 @@
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 @@
@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;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java Tue Mar 12 19:17:42 2019 +0100
@@ -37,11 +37,14 @@
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 @@
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;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java Tue Mar 12 19:17:42 2019 +0100
@@ -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.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.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.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 @@
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 @@
}
}
+ @Override
public Variable emitRor(Value a, Value b) {
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
@@ -1103,65 +1071,36 @@
@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() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java Tue Mar 12 19:17:42 2019 +0100
@@ -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.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.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.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 @@
@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;
}
@@ -635,6 +646,19 @@
}
@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());
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Tue Mar 12 19:17:42 2019 +0100
@@ -83,8 +83,8 @@
@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 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 @@
@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);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/SpeculativeExecutionAttacksMitigations.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/SpeculativeExecutionAttacksMitigations.java Tue Mar 12 19:17:42 2019 +0100
@@ -37,9 +37,9 @@
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
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java Tue Mar 12 19:17:42 2019 +0100
@@ -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 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();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java Tue Mar 12 19:17:42 2019 +0100
@@ -121,7 +121,7 @@
}
}
- for (T block : loop.getExits()) {
+ for (T block : loop.getLoopExits()) {
assert block.getId() >= loop.getHeader().getId();
Loop<?> blockLoop = block.getLoop();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java Tue Mar 12 19:17:42 2019 +0100
@@ -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 @@
this.blocks = new ArrayList<>();
this.children = new ArrayList<>();
this.exits = new ArrayList<>();
+ this.naturalExits = new ArrayList<>();
}
public abstract long numBackedges();
@@ -84,12 +94,87 @@
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 int hashCode() {
return index + depth * 31;
}
+
+ @Override
+ public boolean equals(Object obj) {
+ return super.equals(obj);
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/doc-files/MitigateSpeculativeExecutionAttacksHelp.txt Tue Mar 12 19:17:42 2019 +0100
@@ -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.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractObjectStamp.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractObjectStamp.java Tue Mar 12 19:17:42 2019 +0100
@@ -48,6 +48,13 @@
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
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java Tue Mar 12 19:17:42 2019 +0100
@@ -36,6 +36,12 @@
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;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java Tue Mar 12 19:17:42 2019 +0100
@@ -46,6 +46,10 @@
}
@Override
+ public void accept(Visitor v) {
+ }
+
+ @Override
public JavaKind getStackKind() {
return JavaKind.Illegal;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java Tue Mar 12 19:17:42 2019 +0100
@@ -31,6 +31,7 @@
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 @@
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 +
+ '}';
+ }
+ }
+
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java Tue Mar 12 19:17:42 2019 +0100
@@ -39,6 +39,11 @@
this.bits = bits;
}
+ @Override
+ public void accept(Visitor v) {
+ v.visitInt(bits);
+ }
+
/**
* The width in bits of the value described by this stamp.
*/
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java Tue Mar 12 19:17:42 2019 +0100
@@ -26,6 +26,7 @@
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 @@
/**
* 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 @@
}
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();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampPair.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampPair.java Tue Mar 12 19:17:42 2019 +0100
@@ -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 @@
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;
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/SymbolicJVMCIReference.java Tue Mar 12 19:17:42 2019 +0100
@@ -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);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java Tue Mar 12 19:17:42 2019 +0100
@@ -43,6 +43,10 @@
}
@Override
+ public void accept(Visitor v) {
+ }
+
+ @Override
public Stamp unrestricted() {
return this;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsignedLong.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsignedLong.java Tue Mar 12 19:17:42 2019 +0100
@@ -43,6 +43,10 @@
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;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Tue Mar 12 19:17:42 2019 +0100
@@ -157,6 +157,10 @@
if (className.equals("org.graalvm.compiler.serviceprovider.GraalServices$Lazy")) {
return false;
}
+ } else {
+ if (className.equals("jdk.vm.ci.services.JVMCIClassLoaderFactory")) {
+ return false;
+ }
}
return true;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Tue Mar 12 19:17:42 2019 +0100
@@ -33,7 +33,7 @@
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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest2.java Tue Mar 12 19:17:42 2019 +0100
@@ -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());
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java Tue Mar 12 19:17:42 2019 +0100
@@ -31,6 +31,7 @@
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 @@
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, "*");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Tue Mar 12 19:17:42 2019 +0100
@@ -111,7 +111,7 @@
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 @@
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);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java Tue Mar 12 19:17:42 2019 +0100
@@ -30,16 +30,15 @@
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 @@
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);
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java Tue Mar 12 19:17:42 2019 +0100
@@ -35,6 +35,7 @@
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.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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerDivRemConstantTest.java Tue Mar 12 19:17:42 2019 +0100
@@ -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);