8218074: Update Graal

Reviewed-by: kvn
This commit is contained in:
Jesper Wilhelmsson 2019-03-12 19:17:42 +01:00
parent ebcf4ca1e7
commit c7219faf86
304 changed files with 17324 additions and 8639 deletions

View File

@ -461,6 +461,7 @@ jdk.internal.vm.compiler_EXCLUDES += \
org.graalvm.compiler.debug.test \ org.graalvm.compiler.debug.test \
org.graalvm.compiler.graph.test \ org.graalvm.compiler.graph.test \
org.graalvm.compiler.hotspot.amd64.test \ org.graalvm.compiler.hotspot.amd64.test \
org.graalvm.compiler.hotspot.jdk9.test \
org.graalvm.compiler.hotspot.lir.test \ org.graalvm.compiler.hotspot.lir.test \
org.graalvm.compiler.hotspot.sparc.test \ org.graalvm.compiler.hotspot.sparc.test \
org.graalvm.compiler.hotspot.test \ org.graalvm.compiler.hotspot.test \

View File

@ -92,6 +92,7 @@ ifeq ($(INCLUDE_GRAAL), true)
$(SRC_DIR)/org.graalvm.compiler.debug.test/src \ $(SRC_DIR)/org.graalvm.compiler.debug.test/src \
$(SRC_DIR)/org.graalvm.compiler.graph.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.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.lir.test/src \
$(SRC_DIR)/org.graalvm.compiler.hotspot.sparc.test/src \ $(SRC_DIR)/org.graalvm.compiler.hotspot.sparc.test/src \
$(SRC_DIR)/org.graalvm.compiler.hotspot.test/src \ $(SRC_DIR)/org.graalvm.compiler.hotspot.test/src \

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -29,6 +29,10 @@ import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; 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; import java.util.stream.Stream;
final class Linker { final class Linker {
@ -46,9 +50,12 @@ final class Linker {
return libraryFileName; return libraryFileName;
} }
private static Stream<String> getLines(InputStream stream) {
return new BufferedReader(new InputStreamReader(stream)).lines();
}
private static String getString(InputStream stream) { private static String getString(InputStream stream) {
BufferedReader br = new BufferedReader(new InputStreamReader(stream)); Stream<String> lines = getLines(stream);
Stream<String> lines = br.lines();
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
lines.iterator().forEachRemaining(e -> sb.append(e)); lines.iterator().forEachRemaining(e -> sb.append(e));
return sb.toString(); return sb.toString();
@ -150,9 +157,18 @@ final class Linker {
} }
/** /**
* Search for Visual Studio link.exe Search Order is: VS2013, VS2015, VS2012. * Search for Visual Studio link.exe Search Order is: VS2017+, VS2013, VS2015, VS2012.
*/ */
private static String getWindowsLinkPath() { private static String getWindowsLinkPath() throws Exception {
try {
Path vc141NewerLinker = getVC141AndNewerLinker();
if (vc141NewerLinker != null) {
return vc141NewerLinker.toString();
}
} catch (Exception e) {
e.printStackTrace();
}
String link = "\\VC\\bin\\amd64\\link.exe"; String link = "\\VC\\bin\\amd64\\link.exe";
/** /**
@ -183,10 +199,46 @@ final class Linker {
return null; 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) // @formatter:off (workaround for Eclipse formatting bug)
/**
* Visual Studio supported versions Search Order is: VS2013, VS2015, VS2012.
*/
enum VSVERSIONS { enum VSVERSIONS {
VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"), 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"), VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"),

View File

@ -166,7 +166,7 @@ public final class Main {
printer.printInfo(classesToCompile.size() + " classes found"); printer.printInfo(classesToCompile.size() + " classes found");
} }
OptionValues graalOptions = HotSpotGraalOptionValues.HOTSPOT_OPTIONS; OptionValues graalOptions = HotSpotGraalOptionValues.defaultOptions();
// Setting -Dgraal.TieredAOT overrides --compile-for-tiered // Setting -Dgraal.TieredAOT overrides --compile-for-tiered
if (!TieredAOT.hasBeenSet(graalOptions)) { if (!TieredAOT.hasBeenSet(graalOptions)) {
graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered); graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered);

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,7 @@ import jdk.tools.jaotc.LoadedClass;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.io.File;
public final class ClassSearch { public final class ClassSearch {
private final List<SourceProvider> providers = new ArrayList<>(); private final List<SourceProvider> providers = new ArrayList<>();
@ -106,7 +107,7 @@ public final class ClassSearch {
public static List<SearchFor> makeList(String type, String argument) { public static List<SearchFor> makeList(String type, String argument) {
List<SearchFor> list = new ArrayList<>(); List<SearchFor> list = new ArrayList<>();
String[] elements = argument.split(":"); String[] elements = argument.split(File.pathSeparator);
for (String element : elements) { for (String element : elements) {
list.add(new SearchFor(element, type)); list.add(new SearchFor(element, type));
} }

View File

@ -880,15 +880,15 @@ public abstract class AArch64Assembler extends Assembler {
protected void tbnz(Register reg, int uimm6, int imm16, int pos) { protected void tbnz(Register reg, int uimm6, int imm16, int pos) {
assert reg.getRegisterCategory().equals(CPU); assert reg.getRegisterCategory().equals(CPU);
assert NumUtil.isUnsignedNbit(6, uimm6); assert NumUtil.isUnsignedNbit(6, uimm6);
assert NumUtil.isSignedNbit(18, imm16); assert NumUtil.isSignedNbit(16, imm16) : String.format("Offset value must fit in 16 bits signed: 0x%x", imm16);
assert (imm16 & 3) == 0; 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 // size bit is overloaded as top bit of uimm6 bit index
int size = (((uimm6 >> 5) & 1) == 0 ? 32 : 64); int size = (((uimm6 >> 5) & 1) == 0 ? 32 : 64);
// remaining 5 bits are encoded lower down // remaining 5 bits are encoded lower down
int uimm5 = uimm6 >> 1; int uimm5 = uimm6 & 0x1F;
int offset = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2; int imm14 = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2;
InstructionType type = generalFromSize(size); 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) { if (pos == -1) {
emitInt(encoding); emitInt(encoding);
} else { } else {
@ -907,15 +907,15 @@ public abstract class AArch64Assembler extends Assembler {
protected void tbz(Register reg, int uimm6, int imm16, int pos) { protected void tbz(Register reg, int uimm6, int imm16, int pos) {
assert reg.getRegisterCategory().equals(CPU); assert reg.getRegisterCategory().equals(CPU);
assert NumUtil.isUnsignedNbit(6, uimm6); assert NumUtil.isUnsignedNbit(6, uimm6);
assert NumUtil.isSignedNbit(18, imm16); assert NumUtil.isSignedNbit(16, imm16) : String.format("Offset value must fit in 16 bits signed: 0x%x", imm16);
assert (imm16 & 3) == 0; 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 // size bit is overloaded as top bit of uimm6 bit index
int size = (((uimm6 >> 5) & 1) == 0 ? 32 : 64); int size = (((uimm6 >> 5) & 1) == 0 ? 32 : 64);
// remaining 5 bits are encoded lower down // remaining 5 bits are encoded lower down
int uimm5 = uimm6 >> 1; int uimm5 = uimm6 & 0x1F;
int offset = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2; int imm14 = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2;
InstructionType type = generalFromSize(size); 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) { if (pos == -1) {
emitInt(encoding); emitInt(encoding);
} else { } else {

View File

@ -33,6 +33,9 @@ import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.REG
import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.ADD_TO_BASE; import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.ADD_TO_BASE;
import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.ADD_TO_INDEX; 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 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.CPU;
import static jdk.vm.ci.aarch64.AArch64.r8; import static jdk.vm.ci.aarch64.AArch64.r8;
import static jdk.vm.ci.aarch64.AArch64.r9; import static jdk.vm.ci.aarch64.AArch64.r9;
@ -1452,7 +1455,7 @@ public class AArch64MacroAssembler extends AArch64Assembler {
* *
* @param cmp general purpose register. May not be null, zero-register or stackpointer. * @param cmp general purpose register. May not be null, zero-register or stackpointer.
* @param uimm6 Unsigned 6-bit bit index. * @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) { public void tbnz(Register cmp, int uimm6, Label label) {
assert NumUtil.isUnsignedNbit(6, uimm6); assert NumUtil.isUnsignedNbit(6, uimm6);
@ -1472,7 +1475,7 @@ public class AArch64MacroAssembler extends AArch64Assembler {
* *
* @param cmp general purpose register. May not be null, zero-register or stackpointer. * @param cmp general purpose register. May not be null, zero-register or stackpointer.
* @param uimm6 Unsigned 6-bit bit index. * @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) { public void tbz(Register cmp, int uimm6, Label label) {
assert NumUtil.isUnsignedNbit(6, uimm6); assert NumUtil.isUnsignedNbit(6, uimm6);
@ -1681,6 +1684,9 @@ public class AArch64MacroAssembler extends AArch64Assembler {
int sizeEncoding = information & NumUtil.getNbitNumberInt(6); int sizeEncoding = information & NumUtil.getNbitNumberInt(6);
int regEncoding = information >>> 6; int regEncoding = information >>> 6;
Register reg = AArch64.cpuRegisters.get(regEncoding); Register reg = AArch64.cpuRegisters.get(regEncoding);
if (!NumUtil.isSignedNbit(16, branchOffset)) {
throw new BranchTargetOutOfBoundsException(true, "Branch target %d out of bounds", branchOffset);
}
switch (type) { switch (type) {
case BRANCH_BIT_NONZERO: case BRANCH_BIT_NONZERO:
super.tbnz(reg, sizeEncoding, branchOffset, branch); super.tbnz(reg, sizeEncoding, branchOffset, branch);

View File

@ -683,7 +683,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
emitImmediate(asm, size, imm); emitImmediate(asm, size, imm);
int nextInsnPos = asm.position(); int nextInsnPos = asm.position();
if (annotateImm && asm.codePatchingAnnotationConsumer != null) { if (annotateImm && asm.codePatchingAnnotationConsumer != null) {
asm.codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos)); asm.codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
} }
} }
@ -700,7 +700,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
emitImmediate(asm, size, imm); emitImmediate(asm, size, imm);
int nextInsnPos = asm.position(); int nextInsnPos = asm.position();
if (annotateImm && asm.codePatchingAnnotationConsumer != null) { if (annotateImm && asm.codePatchingAnnotationConsumer != null) {
asm.codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos)); asm.codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
} }
} }
} }
@ -2023,7 +2023,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
emitInt(imm32); emitInt(imm32);
int nextInsnPos = position(); int nextInsnPos = position();
if (annotateImm && codePatchingAnnotationConsumer != null) { if (annotateImm && codePatchingAnnotationConsumer != null) {
codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos)); codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
} }
} }
@ -2201,10 +2201,11 @@ public class AMD64Assembler extends AMD64BaseAssembler {
} }
public final void movswl(Register dst, AMD64Address src) { public final void movswl(Register dst, AMD64Address src) {
prefix(src, dst); AMD64RMOp.MOVSX.emit(this, DWORD, dst, src);
emitByte(0x0F); }
emitByte(0xBF);
emitOperandHelper(dst, src, 0); public final void movswq(Register dst, AMD64Address src) {
AMD64RMOp.MOVSX.emit(this, QWORD, dst, src);
} }
public final void movw(AMD64Address dst, int imm16) { public final void movw(AMD64Address dst, int imm16) {
@ -2222,6 +2223,13 @@ public class AMD64Assembler extends AMD64BaseAssembler {
emitOperandHelper(src, dst, 0); 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) { public final void movzbl(Register dst, AMD64Address src) {
prefix(src, dst); prefix(src, dst);
emitByte(0x0F); emitByte(0x0F);
@ -2237,11 +2245,16 @@ public class AMD64Assembler extends AMD64BaseAssembler {
AMD64RMOp.MOVZXB.emit(this, QWORD, dst, src); 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) { public final void movzwl(Register dst, AMD64Address src) {
prefix(src, dst); AMD64RMOp.MOVZX.emit(this, DWORD, dst, src);
emitByte(0x0F); }
emitByte(0xB7);
emitOperandHelper(dst, src, 0); public final void movzwq(Register dst, AMD64Address src) {
AMD64RMOp.MOVZX.emit(this, QWORD, dst, src);
} }
public final void negl(Register dst) { public final void negl(Register dst) {
@ -2557,16 +2570,63 @@ public class AMD64Assembler extends AMD64BaseAssembler {
emitModRM(dst, src); emitModRM(dst, src);
} }
// Insn: VPMOVZXBW xmm1, xmm2/m64 private void pmovSZx(Register dst, AMD64Address src, int op) {
public final void pmovzxbw(Register dst, AMD64Address src) {
assert supports(CPUFeature.SSE4_1); assert supports(CPUFeature.SSE4_1);
assert inRC(XMM, dst); assert inRC(XMM, dst);
simdPrefix(dst, Register.None, src, PD, P_0F38, false); simdPrefix(dst, Register.None, src, PD, P_0F38, false);
emitByte(0x30); emitByte(op);
emitOperandHelper(dst, src, 0); 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) { public final void pmovzxbw(Register dst, Register src) {
assert supports(CPUFeature.SSE4_1); assert supports(CPUFeature.SSE4_1);
assert inRC(XMM, dst) && inRC(XMM, src); assert inRC(XMM, dst) && inRC(XMM, src);
@ -2881,6 +2941,10 @@ public class AMD64Assembler extends AMD64BaseAssembler {
XOR.rmOp.emit(this, DWORD, dst, src); 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) { public final void xorpd(Register dst, Register src) {
SSEOp.XOR.emit(this, PD, dst, src); SSEOp.XOR.emit(this, PD, dst, src);
} }
@ -3045,7 +3109,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
emitLong(imm64); emitLong(imm64);
int nextInsnPos = position(); int nextInsnPos = position();
if (annotateImm && codePatchingAnnotationConsumer != null) { if (annotateImm && codePatchingAnnotationConsumer != null) {
codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos)); codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
} }
} }
@ -3189,6 +3253,19 @@ public class AMD64Assembler extends AMD64BaseAssembler {
emitModRM(5, dst); 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) { public final void sbbq(Register dst, Register src) {
SBB.rmOp.emit(this, QWORD, dst, src); SBB.rmOp.emit(this, QWORD, dst, src);
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -210,7 +210,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
} }
} }
public abstract static class OperandDataAnnotation extends CodeAnnotation { public static class OperandDataAnnotation extends CodeAnnotation {
/** /**
* The position (bytes from the beginning of the method) of the operand. * The position (bytes from the beginning of the method) of the operand.
*/ */
@ -239,30 +239,10 @@ public abstract class AMD64BaseAssembler extends Assembler {
} }
} }
/**
* Annotation that stores additional information about the displacement of a
* {@link Assembler#getPlaceholder placeholder address} that needs patching.
*/
protected static class AddressDisplacementAnnotation extends OperandDataAnnotation {
AddressDisplacementAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) {
super(instructionPosition, operandPosition, operandSize, nextInstructionPosition);
}
}
/**
* Annotation that stores additional information about the immediate operand, e.g., of a call
* instruction, that needs patching.
*/
protected static class ImmediateOperandAnnotation extends OperandDataAnnotation {
ImmediateOperandAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) {
super(instructionPosition, operandPosition, operandSize, nextInstructionPosition);
}
}
protected void annotatePatchingImmediate(int operandOffset, int operandSize) { protected void annotatePatchingImmediate(int operandOffset, int operandSize) {
if (codePatchingAnnotationConsumer != null) { if (codePatchingAnnotationConsumer != null) {
int pos = position(); int pos = position();
codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(pos, pos + operandOffset, operandSize, pos + operandOffset + operandSize)); codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(pos, pos + operandOffset, operandSize, pos + operandOffset + operandSize));
} }
} }
@ -581,7 +561,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
assert index.equals(Register.None) : "cannot use RIP relative addressing with index register"; assert index.equals(Register.None) : "cannot use RIP relative addressing with index register";
emitByte(0x05 | regenc); emitByte(0x05 | regenc);
if (codePatchingAnnotationConsumer != null && addr.instructionStartPosition >= 0) { 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); emitInt(disp);
} else if (base.isValid()) { } else if (base.isValid()) {

View File

@ -136,9 +136,9 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException;
import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.GraalError;
import jdk.vm.ci.code.Register; import jdk.vm.ci.code.Register;
@ -1281,7 +1281,7 @@ public abstract class SPARCAssembler extends Assembler {
public int setDisp(int inst, int d) { public int setDisp(int inst, int d) {
assert this.match(inst); assert this.match(inst);
if (!isValidDisp(d)) { 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); return this.disp.setBits(inst, d);
} }

View File

@ -32,6 +32,7 @@ import org.graalvm.compiler.api.test.Graal;
import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.code.DisassemblerProvider; import org.graalvm.compiler.code.DisassemblerProvider;
import org.graalvm.compiler.core.common.CompilationIdentifier; 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.core.target.Backend;
import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph;
@ -90,7 +91,7 @@ public abstract class AssemblerTest extends GraalTest {
RegisterConfig registerConfig = codeCache.getRegisterConfig(); RegisterConfig registerConfig = codeCache.getRegisterConfig();
CompilationIdentifier compilationId = backend.getCompilationIdentifier(method); CompilationIdentifier compilationId = backend.getCompilationIdentifier(method);
StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).compilationId(compilationId).build(); 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()); CompilationResult compResult = new CompilationResult(graph.compilationId());
byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc); byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc);

View File

@ -22,41 +22,23 @@
*/ */
package org.graalvm.compiler.java; package org.graalvm.compiler.asm;
import jdk.vm.ci.meta.ResolvedJavaMethod; import org.graalvm.compiler.core.common.GraalBailoutException;
import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
public final class IntegerExactOpSpeculation implements SpeculationReason { @SuppressWarnings("serial")
public class BranchTargetOutOfBoundsException extends GraalBailoutException {
public enum IntegerExactOp { public BranchTargetOutOfBoundsException(boolean permanent, String format, Object... args) {
INTEGER_ADD_EXACT, super(permanent, format, args);
INTEGER_INCREMENT_EXACT,
INTEGER_SUBTRACT_EXACT,
INTEGER_DECREMENT_EXACT,
INTEGER_MULTIPLY_EXACT
} }
protected final String methodDescriptor; public BranchTargetOutOfBoundsException(String format, Object... args) {
protected final IntegerExactOp op; super(format, args);
public IntegerExactOpSpeculation(ResolvedJavaMethod method, IntegerExactOp op) {
this.methodDescriptor = method.format("%H.%n(%p)%R");
this.op = op;
} }
@Override public BranchTargetOutOfBoundsException(Throwable cause, String format, Object... args) {
public int hashCode() { super(cause, format, args);
return methodDescriptor.hashCode() * 31 + op.ordinal();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof IntegerExactOpSpeculation) {
IntegerExactOpSpeculation other = (IntegerExactOpSpeculation) obj;
return op.equals(other.op) && methodDescriptor.equals(other.methodDescriptor);
}
return false;
} }
} }

View File

@ -55,6 +55,7 @@ import jdk.vm.ci.meta.Assumptions.Assumption;
import jdk.vm.ci.meta.InvokeTarget; import jdk.vm.ci.meta.InvokeTarget;
import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod; 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 * Represents the output from compiling a method, including the compiled machine code, associated
@ -220,6 +221,11 @@ public class CompilationResult {
*/ */
private ResolvedJavaMethod[] methods; private ResolvedJavaMethod[] methods;
/**
* The {@link SpeculationLog} log used during compilation.
*/
private SpeculationLog speculationLog;
/** /**
* The list of fields that were accessed from the bytecodes. * The list of fields that were accessed from the bytecodes.
*/ */
@ -372,6 +378,21 @@ public class CompilationResult {
return methods; return methods;
} }
/**
* Sets the {@link SpeculationLog} log used during compilation.
*/
public void setSpeculationLog(SpeculationLog speculationLog) {
checkOpen();
this.speculationLog = speculationLog;
}
/**
* Gets the {@link SpeculationLog} log, if any, used during compilation.
*/
public SpeculationLog getSpeculationLog() {
return speculationLog;
}
/** /**
* Sets the fields that were referenced from the bytecodes that were used as input to the * Sets the fields that were referenced from the bytecodes that were used as input to the
* compilation. * compilation.
@ -615,7 +636,7 @@ public class CompilationResult {
/** /**
* @return the code annotations or {@code null} if there are none * @return the code annotations or {@code null} if there are none
*/ */
public List<CodeAnnotation> getAnnotations() { public List<CodeAnnotation> getCodeAnnotations() {
if (annotations == null) { if (annotations == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -706,7 +727,8 @@ public class CompilationResult {
* Clears the information in this object pertaining to generating code. That is, the * Clears the information in this object pertaining to generating code. That is, the
* {@linkplain #getMarks() marks}, {@linkplain #getInfopoints() infopoints}, * {@linkplain #getMarks() marks}, {@linkplain #getInfopoints() infopoints},
* {@linkplain #getExceptionHandlers() exception handlers}, {@linkplain #getDataPatches() data * {@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() { public void resetForEmittingCode() {
checkOpen(); checkOpen();
@ -721,6 +743,14 @@ public class CompilationResult {
} }
} }
public void clearInfopoints() {
infopoints.clear();
}
public void clearExceptionHandlers() {
exceptionHandlers.clear();
}
private void checkOpen() { private void checkOpen() {
if (closed) { if (closed) {
throw new IllegalStateException(); throw new IllegalStateException();

View File

@ -78,7 +78,7 @@ public class HexCodeFileDisassemblerProvider implements DisassemblerProvider {
long start = installedCode == null ? 0L : installedCode.getStart(); long start = installedCode == null ? 0L : installedCode.getStart();
HexCodeFile hcf = new HexCodeFile(code, start, target.arch.getName(), target.wordSize * 8); HexCodeFile hcf = new HexCodeFile(code, start, target.arch.getName(), target.wordSize * 8);
if (compResult != null) { if (compResult != null) {
HexCodeFile.addAnnotations(hcf, compResult.getAnnotations()); HexCodeFile.addAnnotations(hcf, compResult.getCodeAnnotations());
addExceptionHandlersComment(compResult, hcf); addExceptionHandlersComment(compResult, hcf);
Register fp = regConfig.getFrameRegister(); Register fp = regConfig.getFrameRegister();
RefMapFormatter slotFormatter = new DefaultRefMapFormatter(target.wordSize, fp, 0); RefMapFormatter slotFormatter = new DefaultRefMapFormatter(target.wordSize, fp, 0);

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -484,26 +484,6 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem
getLIRGen().append(new StoreOp(kind, storeAddress, input, state)); getLIRGen().append(new StoreOp(kind, storeAddress, input, state));
} }
@Override
public Value emitMathLog(Value input, boolean base10) {
throw GraalError.unimplemented();
}
@Override
public Value emitMathCos(Value input) {
throw GraalError.unimplemented();
}
@Override
public Value emitMathSin(Value input) {
throw GraalError.unimplemented();
}
@Override
public Value emitMathTan(Value input) {
throw GraalError.unimplemented();
}
@Override @Override
public void emitCompareOp(AArch64Kind cmpKind, Variable left, Value right) { public void emitCompareOp(AArch64Kind cmpKind, Variable left, Value right) {
throw GraalError.unimplemented(); throw GraalError.unimplemented();

View File

@ -52,6 +52,7 @@ import org.graalvm.compiler.lir.aarch64.AArch64ByteSwapOp;
import org.graalvm.compiler.lir.aarch64.AArch64Compare; import org.graalvm.compiler.lir.aarch64.AArch64Compare;
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow;
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.BranchOp; 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.CondMoveOp;
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CondSetOp; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CondSetOp;
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp;
@ -257,6 +258,27 @@ public abstract class AArch64LIRGenerator extends LIRGenerator {
@Override @Override
public void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, public void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
double trueDestinationProbability) { 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); boolean mirrored = emitCompare(cmpKind, left, right, cond, unorderedIsTrue);
Condition finalCondition = mirrored ? cond.mirror() : cond; Condition finalCondition = mirrored ? cond.mirror() : cond;
boolean finalUnorderedIsTrue = mirrored ? !unorderedIsTrue : unorderedIsTrue; boolean finalUnorderedIsTrue = mirrored ? !unorderedIsTrue : unorderedIsTrue;

View File

@ -37,11 +37,14 @@ import org.graalvm.compiler.core.match.ComplexMatchResult;
import org.graalvm.compiler.core.match.MatchRule; import org.graalvm.compiler.core.match.MatchRule;
import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.LIRFrameState;
import org.graalvm.compiler.lir.LabelRef;
import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp; 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.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.DeoptimizingNode; import org.graalvm.compiler.nodes.DeoptimizingNode;
import org.graalvm.compiler.nodes.IfNode;
import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.AddNode;
@ -178,6 +181,28 @@ public class AArch64NodeMatchRules extends NodeMatchRules {
return builder -> getArithmeticLIRGenerator().emitMSub(operand(a), operand(b), operand(c)); 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 @Override
public AArch64LIRGenerator getLIRGeneratorTool() { public AArch64LIRGenerator getLIRGeneratorTool() {
return (AArch64LIRGenerator) gen; return (AArch64LIRGenerator) gen;

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -80,13 +80,6 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
import static org.graalvm.compiler.lir.amd64.AMD64Arithmetic.DREM; 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.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.AMD64BinaryArithmetic;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
@ -116,8 +109,13 @@ import org.graalvm.compiler.lir.amd64.AMD64ArithmeticLIRGeneratorTool;
import org.graalvm.compiler.lir.amd64.AMD64Binary; import org.graalvm.compiler.lir.amd64.AMD64Binary;
import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer; import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer;
import org.graalvm.compiler.lir.amd64.AMD64ClearRegisterOp; import org.graalvm.compiler.lir.amd64.AMD64ClearRegisterOp;
import org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp; import org.graalvm.compiler.lir.amd64.AMD64MathCosOp;
import org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp; 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.AMD64Move;
import org.graalvm.compiler.lir.amd64.AMD64MulDivOp; import org.graalvm.compiler.lir.amd64.AMD64MulDivOp;
import org.graalvm.compiler.lir.amd64.AMD64ShiftOp; import org.graalvm.compiler.lir.amd64.AMD64ShiftOp;
@ -127,7 +125,6 @@ import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary;
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary.AVXBinaryOp; import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary.AVXBinaryOp;
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorUnary; import org.graalvm.compiler.lir.amd64.vector.AMD64VectorUnary;
import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator; 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;
import jdk.vm.ci.amd64.AMD64.CPUFeature; import jdk.vm.ci.amd64.AMD64.CPUFeature;
@ -152,41 +149,11 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
private static final RegisterValue RCX_I = AMD64.rcx.asValue(LIRKind.value(AMD64Kind.DWORD)); 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.nullRegisterValue = nullRegisterValue;
this.maths = maths == null ? new Maths() {
} : maths;
} }
private final AllocatableValue nullRegisterValue; 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 @Override
public Variable emitNegate(Value inputVal) { public Variable emitNegate(Value inputVal) {
@ -781,6 +748,7 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
} }
} }
@Override
public Variable emitRor(Value a, Value b) { public Variable emitRor(Value a, Value b) {
switch ((AMD64Kind) a.getPlatformKind()) { switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD: case DWORD:
@ -1103,65 +1071,36 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
@Override @Override
public Value emitMathLog(Value input, boolean base10) { public Value emitMathLog(Value input, boolean base10) {
LIRGenerator gen = getLIRGen(); if (base10) {
Variable result = maths.emitLog(gen, input, base10); return new AMD64MathLog10Op().emitLIRWrapper(getLIRGen(), input);
if (result == null) { } else {
result = gen.newVariable(LIRKind.combine(input)); return new AMD64MathLogOp().emitLIRWrapper(getLIRGen(), input);
AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), base10 ? LOG10 : LOG, result, asAllocatable(input), stackSlot));
} }
return result;
} }
@Override @Override
public Value emitMathCos(Value input) { public Value emitMathCos(Value input) {
LIRGenerator gen = getLIRGen(); return new AMD64MathCosOp().emitLIRWrapper(getLIRGen(), input);
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;
} }
@Override @Override
public Value emitMathSin(Value input) { public Value emitMathSin(Value input) {
LIRGenerator gen = getLIRGen(); return new AMD64MathSinOp().emitLIRWrapper(getLIRGen(), input);
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;
} }
@Override @Override
public Value emitMathTan(Value input) { public Value emitMathTan(Value input) {
LIRGenerator gen = getLIRGen(); return new AMD64MathTanOp().emitLIRWrapper(getLIRGen(), input);
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;
} }
@Override @Override
public Value emitMathExp(Value input) { public Value emitMathExp(Value input) {
Variable result = getLIRGen().newVariable(LIRKind.combine(input)); return new AMD64MathExpOp().emitLIRWrapper(getLIRGen(), input);
AllocatableValue stackSlot = getLIRGen().getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
getLIRGen().append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), EXP, result, asAllocatable(input), stackSlot));
return result;
} }
@Override @Override
public Value emitMathPow(Value input1, Value input2) { public Value emitMathPow(Value x, Value y) {
Variable result = getLIRGen().newVariable(LIRKind.combine(input1)); return new AMD64MathPowOp().emitLIRWrapper(getLIRGen(), x, y);
getLIRGen().append(new AMD64MathIntrinsicBinaryOp(getAMD64LIRGen(), POW, result, asAllocatable(input1), asAllocatable(input2)));
return result;
} }
protected AMD64LIRGenerator getAMD64LIRGen() { protected AMD64LIRGenerator getAMD64LIRGen() {

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -41,6 +41,8 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
import static org.graalvm.compiler.lir.LIRValueUtil.isIntConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isIntConstant;
import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; 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.AMD64BinaryArithmetic;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
@ -81,6 +83,7 @@ import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatCondSetOp;
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.ReturnOp; import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.ReturnOp;
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.StrategySwitchOp; import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.StrategySwitchOp;
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.TableSwitchOp; 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.AMD64LFenceOp;
import org.graalvm.compiler.lir.amd64.AMD64Move; import org.graalvm.compiler.lir.amd64.AMD64Move;
import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp; import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp;
@ -93,6 +96,7 @@ import org.graalvm.compiler.lir.amd64.AMD64ZapRegistersOp;
import org.graalvm.compiler.lir.amd64.AMD64ZapStackOp; import org.graalvm.compiler.lir.amd64.AMD64ZapStackOp;
import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.gen.LIRGenerator; import org.graalvm.compiler.lir.gen.LIRGenerator;
import org.graalvm.compiler.lir.hashing.Hasher;
import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.phases.util.Providers;
import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64;
@ -545,7 +549,14 @@ public abstract class AMD64LIRGenerator extends LIRGenerator {
@Override @Override
public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers) { public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD)); 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; return result;
} }
@ -634,6 +645,19 @@ public abstract class AMD64LIRGenerator extends LIRGenerator {
append(new TableSwitchOp(lowKey, defaultTarget, targets, key, newVariable(LIRKind.value(target().arch.getWordKind())), newVariable(key.getValueKind()))); append(new TableSwitchOp(lowKey, defaultTarget, targets, key, newVariable(LIRKind.value(target().arch.getWordKind())), newVariable(key.getValueKind())));
} }
@Override
protected Optional<Hasher> hasherFor(JavaConstant[] keyConstants, double minDensity) {
return Hasher.forKeys(keyConstants, minDensity);
}
@Override
protected void emitHashTableSwitch(Hasher hasher, JavaConstant[] keys, LabelRef defaultTarget, LabelRef[] targets, Value value) {
Value index = hasher.hash(value, arithmeticLIRGen);
Variable scratch = newVariable(LIRKind.value(target().arch.getWordKind()));
Variable entryScratch = newVariable(LIRKind.value(target().arch.getWordKind()));
append(new HashTableSwitchOp(keys, defaultTarget, targets, value, index, scratch, entryScratch));
}
@Override @Override
public void emitPause() { public void emitPause() {
append(new AMD64PauseOp()); append(new AMD64PauseOp());

View File

@ -83,8 +83,8 @@ public final class GraalOptions {
@Option(help = "", type = OptionType.Debug) @Option(help = "", type = OptionType.Debug)
public static final OptionKey<String> EscapeAnalyzeOnly = new OptionKey<>(null); public static final OptionKey<String> EscapeAnalyzeOnly = new OptionKey<>(null);
@Option(help = "", type = OptionType.Expert) @Option(help = "The maximum length of an array that will be escape analyzed.", type = OptionType.Expert)
public static final OptionKey<Integer> MaximumEscapeAnalysisArrayLength = new OptionKey<>(32); public static final OptionKey<Integer> MaximumEscapeAnalysisArrayLength = new OptionKey<>(128);
@Option(help = "", type = OptionType.Debug) @Option(help = "", type = OptionType.Debug)
public static final OptionKey<Boolean> PEAInliningHints = new OptionKey<>(false); public static final OptionKey<Boolean> PEAInliningHints = new OptionKey<>(false);
@ -142,7 +142,7 @@ public final class GraalOptions {
public static final OptionKey<Boolean> VerifyPhases = new OptionKey<>(false); public static final OptionKey<Boolean> VerifyPhases = new OptionKey<>(false);
// Debug settings: // 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); public static final OptionKey<Integer> GCDebugStartCycle = new OptionKey<>(-1);
@Option(help = "Perform platform dependent validation of the Java heap at returns", type = OptionType.Debug) @Option(help = "Perform platform dependent validation of the Java heap at returns", type = OptionType.Debug)
@ -206,9 +206,6 @@ public final class GraalOptions {
@Option(help = "Generate position independent code", type = OptionType.Expert) @Option(help = "Generate position independent code", type = OptionType.Expert)
public static final OptionKey<Boolean> GeneratePIC = new OptionKey<>(false); 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 // Runtime settings
@Option(help = "", type = OptionType.Expert) @Option(help = "", type = OptionType.Expert)
public static final OptionKey<Boolean> SupportJsrBytecodes = new OptionKey<>(true); public static final OptionKey<Boolean> SupportJsrBytecodes = new OptionKey<>(true);

View File

@ -37,9 +37,9 @@ public enum SpeculativeExecutionAttacksMitigations {
public static class Options { public static class Options {
// @formatter:off // @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); 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); public static final OptionKey<Boolean> UseIndexMasking = new OptionKey<>(false);
// @formatter:on // @formatter:on
} }

View File

@ -24,6 +24,8 @@
package org.graalvm.compiler.core.common.cfg; package org.graalvm.compiler.core.common.cfg;
import java.util.Comparator;
public abstract class AbstractBlockBase<T extends AbstractBlockBase<T>> { public abstract class AbstractBlockBase<T extends AbstractBlockBase<T>> {
protected int id; protected int id;
@ -171,4 +173,13 @@ public abstract class AbstractBlockBase<T extends AbstractBlockBase<T>> {
public int hashCode() { public int hashCode() {
return id; 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();
} }

View File

@ -121,7 +121,7 @@ public class CFGVerifier {
} }
} }
for (T block : loop.getExits()) { for (T block : loop.getLoopExits()) {
assert block.getId() >= loop.getHeader().getId(); assert block.getId() >= loop.getHeader().getId();
Loop<?> blockLoop = block.getLoop(); Loop<?> blockLoop = block.getLoop();

View File

@ -25,19 +25,28 @@
package org.graalvm.compiler.core.common.cfg; 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.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
public abstract class Loop<T extends AbstractBlockBase<T>> { public abstract class Loop<T extends AbstractBlockBase<T>> {
private final Loop<T> parent; private final Loop<T> parent;
private final List<Loop<T>> children; private final ArrayList<Loop<T>> children;
private final int depth; private final int depth;
private final int index; private final int index;
private final T header; private final T header;
private final List<T> blocks; private final ArrayList<T> blocks;
private final List<T> exits; 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) { protected Loop(Loop<T> parent, int index, T header) {
this.parent = parent; this.parent = parent;
@ -51,6 +60,7 @@ public abstract class Loop<T extends AbstractBlockBase<T>> {
this.blocks = new ArrayList<>(); this.blocks = new ArrayList<>();
this.children = new ArrayList<>(); this.children = new ArrayList<>();
this.exits = new ArrayList<>(); this.exits = new ArrayList<>();
this.naturalExits = new ArrayList<>();
} }
public abstract long numBackedges(); public abstract long numBackedges();
@ -84,12 +94,87 @@ public abstract class Loop<T extends AbstractBlockBase<T>> {
return blocks; 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; return exits;
} }
public void addExit(T t) { public boolean isLoopExit(T block) {
exits.add(t); assert isSorted(exits);
return Collections.binarySearch(exits, block, BLOCK_ID_COMPARATOR) >= 0;
}
/**
* Returns the natural exit points: these are the earliest block that are guaranteed to never
* reach a back-edge.
*
* This can not be used in the context of preserving or using loop-closed form.
*
* @see #getLoopExits()
*/
public ArrayList<T> getNaturalExits() {
return naturalExits;
}
public boolean isNaturalExit(T block) {
assert isSorted(naturalExits);
return Collections.binarySearch(naturalExits, block, BLOCK_ID_COMPARATOR) >= 0;
}
private static <T extends AbstractBlockBase<T>> boolean isSorted(List<T> list) {
int lastId = Integer.MIN_VALUE;
for (AbstractBlockBase<?> block : list) {
if (block.getId() < lastId) {
return false;
}
lastId = block.getId();
}
return true;
} }
/** /**
@ -115,4 +200,9 @@ public abstract class Loop<T extends AbstractBlockBase<T>> {
public int hashCode() { public int hashCode() {
return index + depth * 31; return index + depth * 31;
} }
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
} }

View File

@ -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.

View File

@ -48,6 +48,13 @@ public abstract class AbstractObjectStamp extends AbstractPointerStamp {
this.exactType = exactType; 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); protected abstract AbstractObjectStamp copyWith(ResolvedJavaType newType, boolean newExactType, boolean newNonNull, boolean newAlwaysNull);
@Override @Override

View File

@ -36,6 +36,12 @@ public abstract class AbstractPointerStamp extends Stamp {
private final boolean nonNull; private final boolean nonNull;
private final boolean alwaysNull; private final boolean alwaysNull;
@Override
public void accept(Visitor v) {
v.visitBoolean(nonNull);
v.visitBoolean(alwaysNull);
}
protected AbstractPointerStamp(boolean nonNull, boolean alwaysNull) { protected AbstractPointerStamp(boolean nonNull, boolean alwaysNull) {
this.nonNull = nonNull; this.nonNull = nonNull;
this.alwaysNull = alwaysNull; this.alwaysNull = alwaysNull;

View File

@ -45,6 +45,10 @@ public final class IllegalStamp extends Stamp {
private IllegalStamp() { private IllegalStamp() {
} }
@Override
public void accept(Visitor v) {
}
@Override @Override
public JavaKind getStackKind() { public JavaKind getStackKind() {
return JavaKind.Illegal; return JavaKind.Illegal;

View File

@ -31,6 +31,7 @@ import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.MemoryAccessProvider; import jdk.vm.ci.meta.MemoryAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.UnresolvedJavaType;
public class ObjectStamp extends AbstractObjectStamp { public class ObjectStamp extends AbstractObjectStamp {
@ -92,4 +93,48 @@ public class ObjectStamp extends AbstractObjectStamp {
return null; 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 +
'}';
}
}
} }

View File

@ -39,6 +39,11 @@ public abstract class PrimitiveStamp extends ArithmeticStamp {
this.bits = bits; this.bits = bits;
} }
@Override
public void accept(Visitor v) {
v.visitInt(bits);
}
/** /**
* The width in bits of the value described by this stamp. * The width in bits of the value described by this stamp.
*/ */

View File

@ -26,6 +26,7 @@ package org.graalvm.compiler.core.common.type;
import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.spi.LIRKindTool; 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.Constant;
import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaKind;
@ -36,7 +37,7 @@ import jdk.vm.ci.meta.ResolvedJavaType;
/** /**
* A stamp is the basis for a type system. * A stamp is the basis for a type system.
*/ */
public abstract class Stamp { public abstract class Stamp implements SpeculationContextObject {
protected Stamp() { protected Stamp() {
} }
@ -185,4 +186,15 @@ public abstract class Stamp {
} }
return false; 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();
} }

View File

@ -24,6 +24,8 @@
package org.graalvm.compiler.core.common.type; 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 * 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. * needs a dynamic check to be used.
@ -63,4 +65,22 @@ public final class StampPair {
return trustedStamp + " (unchecked=" + uncheckedStamp + ")"; 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;
}
} }

View File

@ -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);
}

View File

@ -42,6 +42,10 @@ public final class VoidStamp extends Stamp {
private VoidStamp() { private VoidStamp() {
} }
@Override
public void accept(Visitor v) {
}
@Override @Override
public Stamp unrestricted() { public Stamp unrestricted() {
return this; return this;

View File

@ -43,6 +43,10 @@ public final class UnsignedLong {
return Long.compareUnsigned(value, unsignedValue) < 0; return Long.compareUnsigned(value, unsignedValue) < 0;
} }
public boolean isGreaterThan(long unsignedValue) {
return Long.compareUnsigned(value, unsignedValue) > 0;
}
public boolean isLessOrEqualTo(long unsignedValue) { public boolean isLessOrEqualTo(long unsignedValue) {
return Long.compareUnsigned(value, unsignedValue) <= 0; return Long.compareUnsigned(value, unsignedValue) <= 0;
} }

View File

@ -157,6 +157,10 @@ public class CheckGraalInvariants extends GraalCompilerTest {
if (className.equals("org.graalvm.compiler.serviceprovider.GraalServices$Lazy")) { if (className.equals("org.graalvm.compiler.serviceprovider.GraalServices$Lazy")) {
return false; return false;
} }
} else {
if (className.equals("jdk.vm.ci.services.JVMCIClassLoaderFactory")) {
return false;
}
} }
return true; return true;
} }

View File

@ -33,7 +33,7 @@ import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization; import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization;
import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; 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.IterativeConditionalEliminationPhase;
import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase;

View File

@ -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());
}
}

View File

@ -31,6 +31,7 @@ import java.nio.file.Path;
import jdk.internal.vm.compiler.collections.EconomicMap; import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.debug.DebugOptions; import org.graalvm.compiler.debug.DebugOptions;
import org.graalvm.compiler.debug.DebugOptions.PrintGraphTarget;
import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionValues;
import org.junit.Test; import org.junit.Test;
@ -52,7 +53,7 @@ public class DumpPathTest extends GraalCompilerTest {
String[] extensions = new String[]{".cfg", ".bgv", ".graph-strings"}; String[] extensions = new String[]{".cfg", ".bgv", ".graph-strings"};
EconomicMap<OptionKey<?>, Object> overrides = OptionValues.newOptionMap(); EconomicMap<OptionKey<?>, Object> overrides = OptionValues.newOptionMap();
overrides.put(DebugOptions.DumpPath, dumpDirectoryPath.toString()); 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.PrintCanonicalGraphStrings, true);
overrides.put(DebugOptions.Dump, "*"); overrides.put(DebugOptions.Dump, "*");

View File

@ -111,7 +111,7 @@ import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.Phase;
import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.common.CanonicalizerPhase; 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.InliningPhase;
import org.graalvm.compiler.phases.common.inlining.info.InlineInfo; import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy; import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy;
@ -899,11 +899,21 @@ public abstract class GraalCompilerTest extends GraalTest {
return actual; 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) { protected void assertEquals(Result expect, Result actual) {
if (expect.exception != null) { if (expect.exception != null) {
Assert.assertTrue("expected " + expect.exception, actual.exception != null); Assert.assertTrue("expected " + expect.exception, actual.exception != null);
Assert.assertEquals("Exception class", expect.exception.getClass(), actual.exception.getClass()); 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 { } else {
if (actual.exception != null) { if (actual.exception != null) {
throw new AssertionError("expected " + expect.returnValue + " but got an exception", actual.exception); throw new AssertionError("expected " + expect.returnValue + " but got an exception", actual.exception);

View File

@ -30,16 +30,15 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; 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.EncodedGraph;
import org.graalvm.compiler.nodes.GraphEncoder; import org.graalvm.compiler.nodes.GraphEncoder;
import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.tiers.PhaseContext; import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Test;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public class GraphEncoderTest extends GraalCompilerTest { public class GraphEncoderTest extends GraalCompilerTest {
@ -80,7 +79,7 @@ public class GraphEncoderTest extends GraalCompilerTest {
for (StructuredGraph originalGraph : originalGraphs) { for (StructuredGraph originalGraph : originalGraphs) {
EncodedGraph encodedGraph = new EncodedGraph(encoder.getEncoding(), startOffsets.get(originalGraph), encoder.getObjects(), encoder.getNodeClasses(), originalGraph); EncodedGraph encodedGraph = new EncodedGraph(encoder.getEncoding(), startOffsets.get(originalGraph), encoder.getObjects(), encoder.getNodeClasses(), originalGraph);
GraphEncoder.verifyEncoding(originalGraph, encodedGraph, getTarget().arch); encoder.verifyEncoding(originalGraph, encodedGraph);
} }
} }
} }

View File

@ -35,6 +35,7 @@ import java.util.Iterator;
import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.graph.iterators.NodeIterable; 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.GuardNode;
import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.ParameterNode;
import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph;
@ -42,7 +43,6 @@ import org.graalvm.compiler.nodes.calc.IntegerLowerThanNode;
import org.graalvm.compiler.nodes.calc.IsNullNode; import org.graalvm.compiler.nodes.calc.IsNullNode;
import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.phases.common.CanonicalizerPhase; 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.FloatingReadPhase;
import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase;

View File

@ -0,0 +1,293 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, Arm Limited and affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.core.test;
import org.junit.Test;
public class IntegerDivRemConstantTest extends GraalCompilerTest {
public static int intDivPositiveConstant(int val) {
return val / 5;
}
@Test
public void testIntDivPositiveConstant() {
test("intDivPositiveConstant", -10);
test("intDivPositiveConstant", 0);
test("intDivPositiveConstant", 4256);
test("intDivPositiveConstant", Integer.MAX_VALUE);
test("intDivPositiveConstant", Integer.MIN_VALUE);
}
public static int intDivIntegerMax(int val) {
return val / Integer.MAX_VALUE;
}
@Test
public void testIntDivIntegerMax() {
test("intDivIntegerMax", -10);
test("intDivIntegerMax", 0);
test("intDivIntegerMax", 4256);
test("intDivIntegerMax", Integer.MAX_VALUE);
test("intDivIntegerMax", Integer.MIN_VALUE);
}
public static int intDivNegativeConstant(int val) {
return val / -1234;
}
@Test
public void testIntDivNegativeConstant() {
test("intDivNegativeConstant", -123);
test("intDivNegativeConstant", 0);
test("intDivNegativeConstant", 123);
test("intDivNegativeConstant", Integer.MAX_VALUE);
test("intDivNegativeConstant", Integer.MIN_VALUE);
}
public static int intDivIntegerMinOdd(int val) {
return val / (Integer.MIN_VALUE + 1);
}
@Test
public void testIntDivIntegerMinOdd() {
test("intDivIntegerMinOdd", -123);
test("intDivIntegerMinOdd", 0);
test("intDivIntegerMinOdd", 123);
test("intDivIntegerMinOdd", Integer.MAX_VALUE);
test("intDivIntegerMinOdd", Integer.MIN_VALUE);
}
public static long longDivPositiveConstant(long val) {
return val / 35170432;
}
@Test
public void testLongDivPositiveConstant() {
test("longDivPositiveConstant", -1234L);
test("longDivPositiveConstant", 0L);
test("longDivPositiveConstant", 214423L);
test("longDivPositiveConstant", Long.MAX_VALUE);
test("longDivPositiveConstant", Long.MIN_VALUE);
}
public static long longDivLongMax(long val) {
return val / Long.MAX_VALUE;
}
@Test
public void testLongDivLongMax() {
test("longDivLongMax", -1234L);
test("longDivLongMax", 0L);
test("longDivLongMax", 214423L);
test("longDivLongMax", Long.MAX_VALUE);
test("longDivLongMax", Long.MIN_VALUE);
}
public static long longDivNegativeConstant(long val) {
return val / -413;
}
@Test
public void testLongDivNegativeConstant() {
test("longDivNegativeConstant", -43L);
test("longDivNegativeConstant", 0L);
test("longDivNegativeConstant", 147065L);
test("longDivNegativeConstant", Long.MAX_VALUE);
test("longDivNegativeConstant", Long.MIN_VALUE);
}
public static long longDivLongMinOdd(long val) {
return val / (Long.MIN_VALUE + 1);
}
@Test
public void testLongDivLongMinOdd() {
test("longDivLongMinOdd", -1234L);
test("longDivLongMinOdd", 0L);
test("longDivLongMinOdd", 214423L);
test("longDivLongMinOdd", Long.MAX_VALUE);
test("longDivLongMinOdd", Long.MIN_VALUE);
}
public static int intRemPositiveConstant(int val) {
return val % 139968;
}
@Test
public void testIntRemPositiveConstant() {
test("intRemPositiveConstant", -10);
test("intRemPositiveConstant", 0);
test("intRemPositiveConstant", 4256);
test("intRemPositiveConstant", Integer.MAX_VALUE);
test("intRemPositiveConstant", Integer.MIN_VALUE);
}
public static int intRemNegativeConstant(int val) {
return val % -139968;
}
@Test
public void testIntRemNegativeConstant() {
test("intRemNegativeConstant", -10);
test("intRemNegativeConstant", 0);
test("intRemNegativeConstant", 4256);
test("intRemNegativeConstant", Integer.MAX_VALUE);
test("intRemNegativeConstant", Integer.MIN_VALUE);
}
@SuppressWarnings("divzero")
public static int intRemZero(int val) {
return val % 0;
}
@Test
public void testIntRemZero() {
test("intRemZero", -10);
test("intRemZero", 0);
test("intRemZero", 4256);
test("intRemZero", Integer.MAX_VALUE);
test("intRemZero", Integer.MIN_VALUE);
}
public static int intRemMax(int val) {
return val % Integer.MAX_VALUE;
}
@Test
public void testIntRemMax() {
test("intRemMax", -10);
test("intRemMax", 0);
test("intRemMax", 4256);
test("intRemMax", Integer.MAX_VALUE);
test("intRemMax", Integer.MIN_VALUE);
}
public static int intRemMin(int val) {
return val % Integer.MIN_VALUE;
}
@Test
public void testIntRemMin() {
test("intRemMin", -10);
test("intRemMin", 0);
test("intRemMin", 4256);
test("intRemMin", Integer.MAX_VALUE);
test("intRemMin", Integer.MIN_VALUE);
}
public static long longRemPositiveConstant(long val) {
return val % 35170432;
}
public static int intRemPowerOf2(int val) {
return val % 4;
}
@Test
public void testIntRemPowerOf2() {
test("intRemPowerOf2", -10);
test("intRemPowerOf2", 0);
test("intRemPowerOf2", 4256);
test("intRemPowerOf2", Integer.MAX_VALUE);
test("intRemPowerOf2", Integer.MIN_VALUE);
}
@Test
public void testLongRemPositiveConstant() {
test("longRemPositiveConstant", -1234L);
test("longRemPositiveConstant", 0L);
test("longRemPositiveConstant", 214423L);
test("longRemPositiveConstant", Long.MAX_VALUE);
test("longRemPositiveConstant", Long.MIN_VALUE);
}
public static long longRemNegativeConstant(long val) {
return val % -413;
}
@Test
public void testLongRemNegativeConstant() {
test("longRemNegativeConstant", -43L);
test("longRemNegativeConstant", 0L);
test("longRemNegativeConstant", 147065L);
test("longRemNegativeConstant", Long.MAX_VALUE);
test("longRemNegativeConstant", Long.MIN_VALUE);
}
@SuppressWarnings("divzero")
public static long longRemZero(long val) {
return val % 0;
}
@Test
public void testLongRemZero() {
test("longRemZero", -43L);
test("longRemZero", 0L);
test("longRemZero", 147065L);
test("longRemZero", Long.MAX_VALUE);
test("longRemZero", Long.MIN_VALUE);
}
public static long longRemMax(long val) {
return val % Long.MAX_VALUE;
}
@Test
public void testLongRemMax() {
test("longRemMax", -43L);
test("longRemMax", 0L);
test("longRemMax", 147065L);
test("longRemMax", Long.MAX_VALUE);
test("longRemMax", Long.MIN_VALUE);
}
public static long longRemMin(long val) {
return val % Long.MIN_VALUE;
}
@Test
public void testLongRemMin() {
test("longRemMin", -43L);
test("longRemMin", 0L);
test("longRemMin", 147065L);
test("longRemMin", Long.MAX_VALUE);
test("longRemMin", Long.MIN_VALUE);
}
public static long longRemPowerOf2(long val) {
return val % 4L;
}
@Test
public void testLongRemPowerOf2() {
test("longRemPowerOf2", -43L);
test("longRemPowerOf2", 0L);
test("longRemPowerOf2", 147065L);
test("longRemPowerOf2", Long.MAX_VALUE);
test("longRemPowerOf2", Long.MIN_VALUE);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it

View File

@ -161,9 +161,9 @@ public class NestedLoopTest extends GraalCompilerTest {
Assert.assertTrue(containsDirect(innerMostLoop, d, cfg)); Assert.assertTrue(containsDirect(innerMostLoop, d, cfg));
Assert.assertTrue(contains(rootLoop, d, cfg)); Assert.assertTrue(contains(rootLoop, d, cfg));
Assert.assertTrue(contains(nestedLoop, d, cfg)); Assert.assertTrue(contains(nestedLoop, d, cfg));
Assert.assertEquals(rootExits, rootLoop.getExits().size()); Assert.assertEquals(rootExits, rootLoop.getLoopExits().size());
Assert.assertEquals(nestedExits, nestedLoop.getExits().size()); Assert.assertEquals(nestedExits, nestedLoop.getLoopExits().size());
Assert.assertEquals(innerExits, innerMostLoop.getExits().size()); Assert.assertEquals(innerExits, innerMostLoop.getLoopExits().size());
debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
} }

View File

@ -0,0 +1,126 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.core.test;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.junit.Test;
public class SwitchCanonicalizerTest extends GraalCompilerTest {
public int divByPowerOf2(int n) {
switch (n / 8) {
case Integer.MAX_VALUE / 8 + 1:
return hashCode();
default:
return 1;
}
}
@Test
public void testDivByPowerOf2() {
shouldFoldSwitch("divByPowerOf2");
}
public int divByNonPowerOf2(int n) {
switch (n / 7) {
case Integer.MAX_VALUE / 7 + 1:
return hashCode();
default:
return 1;
}
}
@Test
public void testDivByNonPowerOf2() {
shouldFoldSwitch("divByNonPowerOf2");
}
public int remByPowerOf2(int n) {
switch (n % 8) {
case 9:
return hashCode();
default:
return 1;
}
}
@Test
public void testRemByPowerOf2() {
shouldFoldSwitch("remByPowerOf2");
}
public int remByPowerOf2PositiveX(int n) {
int n0 = n > 0 ? 8 : 9;
switch (n0 % 8) {
case 9:
return hashCode();
default:
return 1;
}
}
@Test
public void testRemByPowerOf2PositiveX() {
shouldFoldSwitch("remByPowerOf2PositiveX");
}
public int remByPowerOf2NegativeX(int n) {
int n0 = n > 0 ? -8 : -9;
switch (n0 % 8) {
case 9:
return hashCode();
default:
return 1;
}
}
@Test
public void testRemByPowerOf2NegativeX() {
shouldFoldSwitch("remByPowerOf2NegativeX");
}
public int remByNonPowerOf2(int n) {
switch (n % 7) {
case 9:
return hashCode();
default:
return 1;
}
}
@Test
public void testRemByNonPowerOf2() {
shouldFoldSwitch("remByNonPowerOf2");
}
private void shouldFoldSwitch(String methodName) {
StructuredGraph graph = parseForCompile(getResolvedJavaMethod(methodName));
new CanonicalizerPhase().apply(graph, getDefaultHighTierContext());
assertFalse(graph.hasNode(IntegerSwitchNode.TYPE));
}
}

View File

@ -24,7 +24,7 @@
package org.graalvm.compiler.core.test; package org.graalvm.compiler.core.test;
import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier; import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;

View File

@ -150,7 +150,8 @@ public class VerifyDebugUsage extends VerifyPhase<PhaseContext> {
"org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl.compilePEGraph", "org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl.compilePEGraph",
"org.graalvm.compiler.core.test.VerifyDebugUsageTest$ValidDumpUsagePhase.run", "org.graalvm.compiler.core.test.VerifyDebugUsageTest$ValidDumpUsagePhase.run",
"org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidConcatDumpUsagePhase.run", "org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidConcatDumpUsagePhase.run",
"org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidDumpUsagePhase.run")); "org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidDumpUsagePhase.run",
"org.graalvm.compiler.hotspot.SymbolicSnippetEncoder.verifySnippetEncodeDecode"));
/** /**
* The set of methods allowed to call a {@code Debug.dump(...)} method with the {@code level} * The set of methods allowed to call a {@code Debug.dump(...)} method with the {@code level}
@ -165,7 +166,8 @@ public class VerifyDebugUsage extends VerifyPhase<PhaseContext> {
"org.graalvm.compiler.core.GraalCompiler.emitFrontEnd", "org.graalvm.compiler.core.GraalCompiler.emitFrontEnd",
"org.graalvm.compiler.phases.BasePhase.dumpAfter", "org.graalvm.compiler.phases.BasePhase.dumpAfter",
"org.graalvm.compiler.replacements.ReplacementsImpl$GraphMaker.makeGraph", "org.graalvm.compiler.replacements.ReplacementsImpl$GraphMaker.makeGraph",
"org.graalvm.compiler.replacements.SnippetTemplate.instantiate")); "org.graalvm.compiler.replacements.SnippetTemplate.instantiate",
"org.graalvm.compiler.hotspot.SymbolicSnippetEncoder.verifySnippetEncodeDecode"));
private void verifyParameters(StructuredGraph callerGraph, MethodCallTargetNode debugCallTarget, List<? extends ValueNode> args, ResolvedJavaType stringType, int startArgIdx, private void verifyParameters(StructuredGraph callerGraph, MethodCallTargetNode debugCallTarget, List<? extends ValueNode> args, ResolvedJavaType stringType, int startArgIdx,
int varArgsIndex) { int varArgsIndex) {

View File

@ -25,6 +25,7 @@
package org.graalvm.compiler.core.test.backend; package org.graalvm.compiler.core.test.backend;
import org.graalvm.compiler.core.GraalCompiler; import org.graalvm.compiler.core.GraalCompiler;
import org.graalvm.compiler.core.gen.LIRCompilerBackend;
import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGenerationResult;
@ -52,7 +53,7 @@ public abstract class BackendTest extends GraalCompilerTest {
throw debug.handle(e); throw debug.handle(e);
} }
LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), graph, null, null, createLIRSuites(graph.getOptions())); LIRGenerationResult lirGen = LIRCompilerBackend.emitLIR(getBackend(), graph, null, null, createLIRSuites(graph.getOptions()));
return lirGen; return lirGen;
} }

View File

@ -46,7 +46,7 @@ public final class RethrowDeoptMaterializeTest extends GraalCompilerTest {
@SuppressWarnings("sync-override") @SuppressWarnings("sync-override")
@Override @Override
public final Throwable fillInStackTrace() { public final Throwable fillInStackTrace() {
return null; return this;
} }
} }

View File

@ -293,7 +293,7 @@ public class EscapeAnalysisTest extends EATestBase {
@SuppressWarnings("sync-override") @SuppressWarnings("sync-override")
@Override @Override
public final Throwable fillInStackTrace() { public final Throwable fillInStackTrace() {
return null; return this;
} }
} }

View File

@ -24,42 +24,18 @@
package org.graalvm.compiler.core; package org.graalvm.compiler.core;
import java.util.Collection;
import java.util.List;
import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.core.common.RetryableBailoutException; import org.graalvm.compiler.core.common.RetryableBailoutException;
import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder;
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.core.common.util.CompilationAlarm; import org.graalvm.compiler.core.common.util.CompilationAlarm;
import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.MethodFilter; import org.graalvm.compiler.debug.MethodFilter;
import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.debug.TimerKey;
import org.graalvm.compiler.lir.LIR;
import org.graalvm.compiler.lir.alloc.OutOfRegistersException;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
import org.graalvm.compiler.lir.framemap.FrameMap;
import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.lir.phases.LIRSuites;
import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
import org.graalvm.compiler.nodes.cfg.Block;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
@ -70,17 +46,8 @@ import org.graalvm.compiler.phases.tiers.Suites;
import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.tiers.TargetProvider;
import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.phases.util.Providers;
import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.code.site.ConstantReference;
import jdk.vm.ci.code.site.DataPatch;
import jdk.vm.ci.meta.Assumptions;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ProfilingInfo; import jdk.vm.ci.meta.ProfilingInfo;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.VMConstant;
/** /**
* Static methods for orchestrating the compilation of a {@linkplain StructuredGraph graph}. * Static methods for orchestrating the compilation of a {@linkplain StructuredGraph graph}.
@ -89,9 +56,6 @@ public class GraalCompiler {
private static final TimerKey CompilerTimer = DebugContext.timer("GraalCompiler").doc("Time spent in compilation (excludes code installation)."); private static final TimerKey CompilerTimer = DebugContext.timer("GraalCompiler").doc("Time spent in compilation (excludes code installation).");
private static final TimerKey FrontEnd = DebugContext.timer("FrontEnd").doc("Time spent processing HIR."); private static final TimerKey FrontEnd = DebugContext.timer("FrontEnd").doc("Time spent processing HIR.");
private static final TimerKey EmitLIR = DebugContext.timer("EmitLIR").doc("Time spent generating LIR from HIR.");
private static final TimerKey EmitCode = DebugContext.timer("EmitCode").doc("Time spent generating machine code from LIR.");
private static final TimerKey BackEnd = DebugContext.timer("BackEnd").doc("Time spent in EmitLIR and EmitCode.");
/** /**
* Encapsulates all the inputs to a {@linkplain GraalCompiler#compile(Request) compilation}. * Encapsulates all the inputs to a {@linkplain GraalCompiler#compile(Request) compilation}.
@ -178,7 +142,7 @@ public class GraalCompiler {
assert !r.graph.isFrozen(); assert !r.graph.isFrozen();
try (DebugContext.Scope s0 = debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); DebugCloseable a = CompilerTimer.start(debug)) { try (DebugContext.Scope s0 = debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); DebugCloseable a = CompilerTimer.start(debug)) {
emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites); emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites);
emitBackEnd(r.graph, null, r.installedCodeOwner, r.backend, r.compilationResult, r.factory, null, r.lirSuites); r.backend.emitBackEnd(r.graph, null, r.installedCodeOwner, r.compilationResult, r.factory, null, r.lirSuites);
if (r.verifySourcePositions) { if (r.verifySourcePositions) {
assert r.graph.verifySourcePositions(true); assert r.graph.verifySourcePositions(true);
} }
@ -275,85 +239,6 @@ public class GraalCompiler {
} }
} }
@SuppressWarnings("try")
public static <T extends CompilationResult> void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult,
CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) {
DebugContext debug = graph.getDebug();
try (DebugContext.Scope s = debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start(debug)) {
LIRGenerationResult lirGen = null;
lirGen = emitLIR(backend, graph, stub, registerConfig, lirSuites);
try (DebugContext.Scope s2 = debug.scope("CodeGen", lirGen, lirGen.getLIR())) {
int bytecodeSize = graph.method() == null ? 0 : graph.getBytecodeSize();
compilationResult.setHasUnsafeAccess(graph.hasUnsafeAccess());
emitCode(backend, graph.getAssumptions(), graph.method(), graph.getMethods(), graph.getFields(), bytecodeSize, lirGen, compilationResult, installedCodeOwner, factory);
} catch (Throwable e) {
throw debug.handle(e);
}
} catch (Throwable e) {
throw debug.handle(e);
} finally {
graph.checkCancellation();
}
}
@SuppressWarnings("try")
public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) {
String registerPressure = GraalOptions.RegisterPressure.getValue(graph.getOptions());
String[] allocationRestrictedTo = registerPressure == null ? null : registerPressure.split(",");
try {
return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo);
} catch (OutOfRegistersException e) {
if (allocationRestrictedTo != null) {
allocationRestrictedTo = null;
return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo);
}
/* If the re-execution fails we convert the exception into a "hard" failure */
throw new GraalError(e);
} finally {
graph.checkCancellation();
}
}
@SuppressWarnings("try")
private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites,
String[] allocationRestrictedTo) {
DebugContext debug = graph.getDebug();
try (DebugContext.Scope ds = debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start(debug)) {
assert !graph.hasValueProxies();
ScheduleResult schedule = graph.getLastSchedule();
Block[] blocks = schedule.getCFG().getBlocks();
Block startBlock = schedule.getCFG().getStartBlock();
assert startBlock != null;
assert startBlock.getPredecessorCount() == 0;
AbstractBlockBase<?>[] codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock);
AbstractBlockBase<?>[] linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock);
LIR lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions(), graph.getDebug());
FrameMapBuilder frameMapBuilder = backend.newFrameMapBuilder(registerConfig);
LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(graph.compilationId(), lir, frameMapBuilder, graph, stub);
LIRGeneratorTool lirGen = backend.newLIRGenerator(lirGenRes);
NodeLIRBuilderTool nodeLirGen = backend.newNodeLIRBuilder(graph, lirGen);
// LIR generation
LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule);
new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context);
try (DebugContext.Scope s = debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) {
// Dump LIR along with HIR (the LIR is looked up from context)
debug.dump(DebugContext.BASIC_LEVEL, graph.getLastSchedule(), "After LIR generation");
LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo));
return result;
} catch (Throwable e) {
throw debug.handle(e);
}
} catch (Throwable e) {
throw debug.handle(e);
} finally {
graph.checkCancellation();
}
}
protected static <T extends CompilationResult> String getCompilationUnitName(StructuredGraph graph, T compilationResult) { protected static <T extends CompilationResult> String getCompilationUnitName(StructuredGraph graph, T compilationResult) {
if (compilationResult != null && compilationResult.getName() != null) { if (compilationResult != null && compilationResult.getName() != null) {
return compilationResult.getName(); return compilationResult.getName();
@ -364,70 +249,4 @@ public class GraalCompiler {
} }
return method.format("%H.%n(%p)"); return method.format("%H.%n(%p)");
} }
public static LIRGenerationResult emitLowLevel(TargetDescription target, LIRGenerationResult lirGenRes, LIRGeneratorTool lirGen, LIRSuites lirSuites,
RegisterAllocationConfig registerAllocationConfig) {
DebugContext debug = lirGenRes.getLIR().getDebug();
PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen);
lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, preAllocOptContext);
debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PreAllocationOptimizationStage");
AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig);
lirSuites.getAllocationStage().apply(target, lirGenRes, allocContext);
debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After AllocationStage");
PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen);
lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, postAllocOptContext);
debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PostAllocationOptimizationStage");
return lirGenRes;
}
@SuppressWarnings("try")
public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Collection<ResolvedJavaMethod> inlinedMethods, EconomicSet<ResolvedJavaField> accessedFields,
int bytecodeSize, LIRGenerationResult lirGenRes,
CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) {
DebugContext debug = lirGenRes.getLIR().getDebug();
try (DebugCloseable a = EmitCode.start(debug)) {
FrameMap frameMap = lirGenRes.getFrameMap();
CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory);
backend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner);
if (assumptions != null && !assumptions.isEmpty()) {
compilationResult.setAssumptions(assumptions.toArray());
}
if (rootMethod != null) {
compilationResult.setMethods(rootMethod, inlinedMethods);
compilationResult.setFields(accessedFields);
compilationResult.setBytecodeSize(bytecodeSize);
}
crb.finish();
if (debug.isCountEnabled()) {
List<DataPatch> ldp = compilationResult.getDataPatches();
JavaKind[] kindValues = JavaKind.values();
CounterKey[] dms = new CounterKey[kindValues.length];
for (int i = 0; i < dms.length; i++) {
dms[i] = DebugContext.counter("DataPatches-%s", kindValues[i]);
}
for (DataPatch dp : ldp) {
JavaKind kind = JavaKind.Illegal;
if (dp.reference instanceof ConstantReference) {
VMConstant constant = ((ConstantReference) dp.reference).getConstant();
if (constant instanceof JavaConstant) {
kind = ((JavaConstant) constant).getJavaKind();
}
}
dms[kind.ordinal()].add(debug, 1);
}
DebugContext.counter("CompilationResults").increment(debug);
DebugContext.counter("CodeBytesEmitted").add(debug, compilationResult.getTargetCodeSize());
DebugContext.counter("InfopointsEmitted").add(debug, compilationResult.getInfopoints().size());
DebugContext.counter("DataPatches").add(debug, ldp.size());
DebugContext.counter("ExceptionHandlersEmitted").add(debug, compilationResult.getExceptionHandlers().size());
}
debug.dump(DebugContext.BASIC_LEVEL, compilationResult, "After code generation");
}
}
} }

View File

@ -0,0 +1,245 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.core.gen;
import java.util.Collection;
import java.util.List;
import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.LIRGenerationPhase;
import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder;
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.TimerKey;
import org.graalvm.compiler.lir.LIR;
import org.graalvm.compiler.lir.alloc.OutOfRegistersException;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
import org.graalvm.compiler.lir.framemap.FrameMap;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
import org.graalvm.compiler.lir.phases.LIRSuites;
import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
import org.graalvm.compiler.nodes.cfg.Block;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.code.site.ConstantReference;
import jdk.vm.ci.code.site.DataPatch;
import jdk.vm.ci.meta.Assumptions;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.SpeculationLog;
import jdk.vm.ci.meta.VMConstant;
public class LIRCompilerBackend {
private static final TimerKey EmitLIR = DebugContext.timer("EmitLIR").doc("Time spent generating LIR from HIR.");
private static final TimerKey EmitCode = DebugContext.timer("EmitCode").doc("Time spent generating machine code from LIR.");
private static final TimerKey BackEnd = DebugContext.timer("BackEnd").doc("Time spent in EmitLIR and EmitCode.");
@SuppressWarnings("try")
public static <T extends CompilationResult> void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult,
CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) {
DebugContext debug = graph.getDebug();
try (DebugContext.Scope s = debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start(debug)) {
LIRGenerationResult lirGen = null;
lirGen = emitLIR(backend, graph, stub, registerConfig, lirSuites);
try (DebugContext.Scope s2 = debug.scope("CodeGen", lirGen, lirGen.getLIR())) {
int bytecodeSize = graph.method() == null ? 0 : graph.getBytecodeSize();
compilationResult.setHasUnsafeAccess(graph.hasUnsafeAccess());
emitCode(backend,
graph.getAssumptions(),
graph.method(),
graph.getMethods(),
graph.getFields(),
graph.getSpeculationLog(),
bytecodeSize,
lirGen,
compilationResult,
installedCodeOwner,
factory);
} catch (Throwable e) {
throw debug.handle(e);
}
} catch (Throwable e) {
throw debug.handle(e);
} finally {
graph.checkCancellation();
}
}
@SuppressWarnings("try")
public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) {
String registerPressure = GraalOptions.RegisterPressure.getValue(graph.getOptions());
String[] allocationRestrictedTo = registerPressure == null ? null : registerPressure.split(",");
try {
return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo);
} catch (OutOfRegistersException e) {
if (allocationRestrictedTo != null) {
allocationRestrictedTo = null;
return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo);
}
/* If the re-execution fails we convert the exception into a "hard" failure */
throw new GraalError(e);
} finally {
graph.checkCancellation();
}
}
@SuppressWarnings("try")
private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites,
String[] allocationRestrictedTo) {
DebugContext debug = graph.getDebug();
try (DebugContext.Scope ds = debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start(debug)) {
assert !graph.hasValueProxies();
ScheduleResult schedule = graph.getLastSchedule();
Block[] blocks = schedule.getCFG().getBlocks();
Block startBlock = schedule.getCFG().getStartBlock();
assert startBlock != null;
assert startBlock.getPredecessorCount() == 0;
AbstractBlockBase<?>[] codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock);
AbstractBlockBase<?>[] linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock);
LIR lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions(), graph.getDebug());
LIRGenerationProvider lirBackend = (LIRGenerationProvider) backend;
LIRGenerationResult lirGenRes = lirBackend.newLIRGenerationResult(graph.compilationId(), lir, registerConfig, graph, stub);
LIRGeneratorTool lirGen = lirBackend.newLIRGenerator(lirGenRes);
NodeLIRBuilderTool nodeLirGen = lirBackend.newNodeLIRBuilder(graph, lirGen);
// LIR generation
LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule);
new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context);
try (DebugContext.Scope s = debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) {
// Dump LIR along with HIR (the LIR is looked up from context)
debug.dump(DebugContext.BASIC_LEVEL, graph.getLastSchedule(), "After LIR generation");
LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo));
return result;
} catch (Throwable e) {
throw debug.handle(e);
}
} catch (Throwable e) {
throw debug.handle(e);
} finally {
graph.checkCancellation();
}
}
private static LIRGenerationResult emitLowLevel(TargetDescription target, LIRGenerationResult lirGenRes, LIRGeneratorTool lirGen, LIRSuites lirSuites,
RegisterAllocationConfig registerAllocationConfig) {
DebugContext debug = lirGenRes.getLIR().getDebug();
PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen);
lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, preAllocOptContext);
debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PreAllocationOptimizationStage");
AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig);
lirSuites.getAllocationStage().apply(target, lirGenRes, allocContext);
debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After AllocationStage");
PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen);
lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, postAllocOptContext);
debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PostAllocationOptimizationStage");
return lirGenRes;
}
@SuppressWarnings("try")
public static void emitCode(Backend backend,
Assumptions assumptions,
ResolvedJavaMethod rootMethod,
Collection<ResolvedJavaMethod> inlinedMethods,
EconomicSet<ResolvedJavaField> accessedFields,
SpeculationLog speculationLog,
int bytecodeSize,
LIRGenerationResult lirGenRes,
CompilationResult compilationResult,
ResolvedJavaMethod installedCodeOwner,
CompilationResultBuilderFactory factory) {
DebugContext debug = lirGenRes.getLIR().getDebug();
try (DebugCloseable a = EmitCode.start(debug)) {
LIRGenerationProvider lirBackend = (LIRGenerationProvider) backend;
FrameMap frameMap = lirGenRes.getFrameMap();
CompilationResultBuilder crb = lirBackend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory);
lirBackend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner);
if (assumptions != null && !assumptions.isEmpty()) {
compilationResult.setAssumptions(assumptions.toArray());
}
if (rootMethod != null) {
compilationResult.setMethods(rootMethod, inlinedMethods);
compilationResult.setFields(accessedFields);
compilationResult.setBytecodeSize(bytecodeSize);
}
if (speculationLog != null) {
compilationResult.setSpeculationLog(speculationLog);
}
crb.finish();
if (debug.isCountEnabled()) {
List<DataPatch> ldp = compilationResult.getDataPatches();
JavaKind[] kindValues = JavaKind.values();
CounterKey[] dms = new CounterKey[kindValues.length];
for (int i = 0; i < dms.length; i++) {
dms[i] = DebugContext.counter("DataPatches-%s", kindValues[i]);
}
for (DataPatch dp : ldp) {
JavaKind kind = JavaKind.Illegal;
if (dp.reference instanceof ConstantReference) {
VMConstant constant = ((ConstantReference) dp.reference).getConstant();
if (constant instanceof JavaConstant) {
kind = ((JavaConstant) constant).getJavaKind();
}
}
dms[kind.ordinal()].add(debug, 1);
}
DebugContext.counter("CompilationResults").increment(debug);
DebugContext.counter("CodeBytesEmitted").add(debug, compilationResult.getTargetCodeSize());
DebugContext.counter("InfopointsEmitted").add(debug, compilationResult.getInfopoints().size());
DebugContext.counter("DataPatches").add(debug, ldp.size());
DebugContext.counter("ExceptionHandlersEmitted").add(debug, compilationResult.getExceptionHandlers().size());
}
debug.dump(DebugContext.BASIC_LEVEL, compilationResult, "After code generation");
}
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.core.gen;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.lir.LIR;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
import org.graalvm.compiler.lir.framemap.FrameMap;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.meta.ResolvedJavaMethod;
/**
* Provides compiler backend-specific generation helpers for the {@link LIRCompilerBackend}.
*/
public interface LIRGenerationProvider {
LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes);
LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph,
Object stub);
NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen);
/**
* Creates the object used to fill in the details of a given compilation result.
*/
CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, FrameMap frameMap, CompilationResult compilationResult,
CompilationResultBuilderFactory factory);
/**
* Emits the code for a given graph.
*
* @param installedCodeOwner the method the compiled code will be associated with once
* installed. This argument can be null.
*/
void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner);
}

View File

@ -768,4 +768,13 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio
public LIRGeneratorTool getLIRGeneratorTool() { public LIRGeneratorTool getLIRGeneratorTool() {
return gen; return gen;
} }
@Override
public void emitReadExceptionObject(ValueNode node) {
LIRGeneratorTool lirGenTool = getLIRGeneratorTool();
Value returnRegister = lirGenTool.getRegisterConfig().getReturnRegister(node.getStackKind()).asValue(
LIRKind.fromJavaKind(lirGenTool.target().arch, node.getStackKind()));
lirGenTool.emitIncomingValues(new Value[]{returnRegister});
setResult(node, lirGenTool.emitMove(returnRegister));
}
} }

View File

@ -47,7 +47,7 @@ import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
import org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase; import org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase;
import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;

View File

@ -39,6 +39,7 @@ import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
import org.graalvm.compiler.phases.common.ExpandLogicPhase; import org.graalvm.compiler.phases.common.ExpandLogicPhase;
import org.graalvm.compiler.phases.common.FixReadsPhase; import org.graalvm.compiler.phases.common.FixReadsPhase;
import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.common.OptimizeDivPhase;
import org.graalvm.compiler.phases.common.ProfileCompiledMethodsPhase; import org.graalvm.compiler.phases.common.ProfileCompiledMethodsPhase;
import org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase; import org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase;
import org.graalvm.compiler.phases.common.UseTrappingNullChecksPhase; import org.graalvm.compiler.phases.common.UseTrappingNullChecksPhase;
@ -72,6 +73,8 @@ public class LowTier extends PhaseSuite<LowTierContext> {
appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER)); appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER));
appendPhase(new OptimizeDivPhase());
appendPhase(new ExpandLogicPhase()); appendPhase(new ExpandLogicPhase());
appendPhase(new FixReadsPhase(true, new SchedulePhase(GraalOptions.StressTestEarlyReads.getValue(options) ? SchedulingStrategy.EARLIEST : SchedulingStrategy.LATEST_OUT_OF_LOOPS))); appendPhase(new FixReadsPhase(true, new SchedulePhase(GraalOptions.StressTestEarlyReads.getValue(options) ? SchedulingStrategy.EARLIEST : SchedulingStrategy.LATEST_OUT_OF_LOOPS)));

View File

@ -26,24 +26,17 @@ package org.graalvm.compiler.core.target;
import java.util.ArrayList; import java.util.ArrayList;
import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
import org.graalvm.compiler.core.gen.LIRCompilerBackend;
import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.lir.LIR;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.lir.phases.LIRSuites;
import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.tiers.SuitesProvider; import org.graalvm.compiler.phases.tiers.SuitesProvider;
import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.tiers.TargetProvider;
@ -54,7 +47,6 @@ import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.code.CompilationRequest;
import jdk.vm.ci.code.CompiledCode; import jdk.vm.ci.code.CompiledCode;
import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.InstalledCode;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.code.ValueKindFactory; import jdk.vm.ci.code.ValueKindFactory;
@ -62,7 +54,6 @@ import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.SpeculationLog;
/** /**
* Represents a compiler backend for Graal. * Represents a compiler backend for Graal.
@ -116,12 +107,6 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
return LIRKind.fromJavaKind(getTarget().arch, javaKind); return LIRKind.fromJavaKind(getTarget().arch, javaKind);
} }
/**
* The given registerConfig is optional, in case null is passed the default RegisterConfig from
* the CodeCacheProvider will be used.
*/
public abstract FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig);
/** /**
* Creates a new configuration for register allocation. * Creates a new configuration for register allocation.
* *
@ -130,26 +115,6 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
*/ */
public abstract RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo); public abstract RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo);
public abstract FrameMap newFrameMap(RegisterConfig registerConfig);
public abstract LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes);
public abstract LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph,
Object stub);
public abstract NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen);
/**
* Creates the assembler used to emit the machine code.
*/
protected abstract Assembler createAssembler(FrameMap frameMap);
/**
* Creates the object used to fill in the details of a given compilation result.
*/
public abstract CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, FrameMap frameMap, CompilationResult compilationResult,
CompilationResultBuilderFactory factory);
/** /**
* Turns a Graal {@link CompilationResult} into a {@link CompiledCode} object that can be passed * Turns a Graal {@link CompilationResult} into a {@link CompiledCode} object that can be passed
* to the VM for code installation. * to the VM for code installation.
@ -158,21 +123,28 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
/** /**
* @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest, * @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest,
* CompilationResult, SpeculationLog, InstalledCode, boolean, Object[]) * CompilationResult, InstalledCode, boolean, Object[])
*/ */
public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult, public InstalledCode createInstalledCode(DebugContext debug,
SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault) { ResolvedJavaMethod method,
return createInstalledCode(debug, method, null, compilationResult, speculationLog, predefinedInstalledCode, isDefault, null); CompilationResult compilationResult,
InstalledCode predefinedInstalledCode,
boolean isDefault) {
return createInstalledCode(debug, method, null, compilationResult, predefinedInstalledCode, isDefault, null);
} }
/** /**
* @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest, * @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest,
* CompilationResult, SpeculationLog, InstalledCode, boolean, Object[]) * CompilationResult, InstalledCode, boolean, Object[])
*/ */
@SuppressWarnings("try") @SuppressWarnings("try")
public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult, public InstalledCode createInstalledCode(DebugContext debug,
SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault) { ResolvedJavaMethod method,
return createInstalledCode(debug, method, compilationRequest, compilationResult, speculationLog, predefinedInstalledCode, isDefault, null); CompilationRequest compilationRequest,
CompilationResult compilationResult,
InstalledCode predefinedInstalledCode,
boolean isDefault) {
return createInstalledCode(debug, method, compilationRequest, compilationResult, predefinedInstalledCode, isDefault, null);
} }
/** /**
@ -185,7 +157,6 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
* @param predefinedInstalledCode a pre-allocated {@link InstalledCode} object to use as a * @param predefinedInstalledCode a pre-allocated {@link InstalledCode} object to use as a
* reference to the installed code. If {@code null}, a new {@link InstalledCode} * reference to the installed code. If {@code null}, a new {@link InstalledCode}
* object will be created. * object will be created.
* @param speculationLog the speculation log to be used
* @param isDefault specifies if the installed code should be made the default implementation of * @param isDefault specifies if the installed code should be made the default implementation of
* {@code compRequest.getMethod()}. The default implementation for a method is the * {@code compRequest.getMethod()}. The default implementation for a method is the
* code executed for standard calls to the method. This argument is ignored if * code executed for standard calls to the method. This argument is ignored if
@ -198,8 +169,13 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
* {@link InstalledCode} object * {@link InstalledCode} object
*/ */
@SuppressWarnings("try") @SuppressWarnings("try")
public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult, public InstalledCode createInstalledCode(DebugContext debug,
SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault, Object[] context) { ResolvedJavaMethod method,
CompilationRequest compilationRequest,
CompilationResult compilationResult,
InstalledCode predefinedInstalledCode,
boolean isDefault,
Object[] context) {
Object[] debugContext = context != null ? context : new Object[]{getProviders().getCodeCache(), method, compilationResult}; Object[] debugContext = context != null ? context : new Object[]{getProviders().getCodeCache(), method, compilationResult};
CodeInstallationTask[] tasks; CodeInstallationTask[] tasks;
synchronized (this) { synchronized (this) {
@ -215,7 +191,7 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
try { try {
preCodeInstallationTasks(tasks, compilationResult); preCodeInstallationTasks(tasks, compilationResult);
CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult, isDefault, debug.getOptions()); CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult, isDefault, debug.getOptions());
installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault); installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, compilationResult.getSpeculationLog(), isDefault);
assert predefinedInstalledCode == null || installedCode == predefinedInstalledCode; assert predefinedInstalledCode == null || installedCode == predefinedInstalledCode;
} catch (Throwable t) { } catch (Throwable t) {
failCodeInstallationTasks(tasks, t); failCodeInstallationTasks(tasks, t);
@ -259,12 +235,15 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
* @param method the method compiled to produce {@code compiledCode} or {@code null} if the * @param method the method compiled to produce {@code compiledCode} or {@code null} if the
* input to {@code compResult} was not a {@link ResolvedJavaMethod} * input to {@code compResult} was not a {@link ResolvedJavaMethod}
* @param compilationRequest the request or {@code null} * @param compilationRequest the request or {@code null}
* @param compilationResult the code to be compiled * @param compilationResult the compiled code
* @return a reference to the compiled and ready-to-run installed code * @return a reference to the compiled and ready-to-run installed code
* @throws BailoutException if the code installation failed * @throws BailoutException if the code installation failed
*/ */
public InstalledCode addInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult) { public InstalledCode addInstalledCode(DebugContext debug,
return createInstalledCode(debug, method, compilationRequest, compilationResult, null, null, false); ResolvedJavaMethod method,
CompilationRequest compilationRequest,
CompilationResult compilationResult) {
return createInstalledCode(debug, method, compilationRequest, compilationResult, null, false);
} }
/** /**
@ -273,29 +252,15 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
* *
* @param method the method compiled to produce {@code compiledCode} or {@code null} if the * @param method the method compiled to produce {@code compiledCode} or {@code null} if the
* input to {@code compResult} was not a {@link ResolvedJavaMethod} * input to {@code compResult} was not a {@link ResolvedJavaMethod}
* @param compilationResult the code to be compiled * @param compilationResult the compiled code
* @return a reference to the compiled and ready-to-run installed code * @return a reference to the compiled and ready-to-run installed code
* @throws BailoutException if the code installation failed * @throws BailoutException if the code installation failed
*/ */
public InstalledCode createDefaultInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult) { public InstalledCode createDefaultInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult) {
return createInstalledCode(debug, method, compilationResult, null, null, true); System.out.println(compilationResult.getSpeculationLog());
return createInstalledCode(debug, method, compilationResult, null, true);
} }
/**
* Emits the code for a given graph.
*
* @param installedCodeOwner the method the compiled code will be associated with once
* installed. This argument can be null.
*/
public abstract void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner);
/**
* Translates a set of registers from the callee's perspective to the caller's perspective. This
* is needed for architectures where input/output registers are renamed during a call (e.g.
* register windows on SPARC). Registers which are not visible by the caller are removed.
*/
public abstract EconomicSet<Register> translateToCallerRegisters(EconomicSet<Register> calleeRegisters);
/** /**
* Gets the compilation id for a given {@link ResolvedJavaMethod}. Returns * Gets the compilation id for a given {@link ResolvedJavaMethod}. Returns
* {@code CompilationIdentifier#INVALID_COMPILATION_ID} in case there is no such id. * {@code CompilationIdentifier#INVALID_COMPILATION_ID} in case there is no such id.
@ -306,6 +271,15 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
return CompilationIdentifier.INVALID_COMPILATION_ID; return CompilationIdentifier.INVALID_COMPILATION_ID;
} }
public void emitBackEnd(StructuredGraph graph,
Object stub,
ResolvedJavaMethod installedCodeOwner,
CompilationResult compilationResult,
CompilationResultBuilderFactory factory,
RegisterConfig config, LIRSuites lirSuites) {
LIRCompilerBackend.emitBackEnd(graph, stub, installedCodeOwner, this, compilationResult, factory, config, lirSuites);
}
/** /**
* Encapsulates custom tasks done before and after code installation. * Encapsulates custom tasks done before and after code installation.
*/ */

View File

@ -450,11 +450,11 @@ public final class DebugContext implements AutoCloseable {
} }
} }
public Path getDumpPath(String extension, boolean directory) { public Path getDumpPath(String extension, boolean createMissingDirectory) {
try { try {
String id = description == null ? null : description.identifier; String id = description == null ? null : description.identifier;
String label = description == null ? null : description.getLabel(); String label = description == null ? null : description.getLabel();
Path result = PathUtilities.createUnique(immutable.options, DumpPath, id, label, extension, directory); Path result = PathUtilities.createUnique(immutable.options, DumpPath, id, label, extension, createMissingDirectory);
if (ShowDumpFiles.getValue(immutable.options)) { if (ShowDumpFiles.getValue(immutable.options)) {
TTY.println("Dumping debug output to %s", result.toAbsolutePath().toString()); TTY.println("Dumping debug output to %s", result.toAbsolutePath().toString());
} }
@ -807,8 +807,9 @@ public final class DebugContext implements AutoCloseable {
return true; return true;
} }
return !currentScope.isTopLevel(); return !currentScope.isTopLevel();
} else {
return false;
} }
return immutable.scopesEnabled && currentScope == null;
} }
class DisabledScope implements DebugContext.Scope { class DisabledScope implements DebugContext.Scope {

View File

@ -30,6 +30,7 @@ import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import jdk.internal.vm.compiler.collections.EconomicMap; import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.options.EnumOptionKey;
import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionType;
@ -40,20 +41,28 @@ import org.graalvm.compiler.serviceprovider.GraalServices;
* Options that configure a {@link DebugContext} and related functionality. * Options that configure a {@link DebugContext} and related functionality.
*/ */
public class DebugOptions { public class DebugOptions {
static class DeprecatedOptionKey<T> extends OptionKey<T> {
private final OptionKey<T> replacement;
DeprecatedOptionKey(OptionKey<T> replacement) { /**
super(replacement.getDefaultValue()); * Values for the {@link DebugOptions#PrintGraph} option denoting where graphs dumped as a
this.replacement = replacement; * result of the {@link DebugOptions#Dump} option are sent.
} */
public enum PrintGraphTarget {
/**
* Dump graphs to files.
*/
File,
@Override /**
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, T oldValue, T newValue) { * Dump graphs to the network. The network destination is specified by the
// Ideally we'd use TTY here but it may not yet be initialized. * {@link DebugOptions#PrintGraphHost} and {@link DebugOptions#PrintGraphPort} options. If a
System.err.printf("Warning: the %s option is deprecated - use %s instead%n", getName(), replacement.getName()); * network connection cannot be opened, dumping falls back to {@link #File} dumping.
replacement.update(values, newValue); */
} Network,
/**
* Do not dump graphs.
*/
Disable;
} }
// @formatter:off // @formatter:off
@ -118,7 +127,7 @@ public class DebugOptions {
public static final OptionKey<Boolean> LogVerbose = new OptionKey<>(false); public static final OptionKey<Boolean> LogVerbose = new OptionKey<>(false);
@Option(help = "The directory where various Graal dump files are written.") @Option(help = "The directory where various Graal dump files are written.")
public static final OptionKey<String> DumpPath = new OptionKey<>("dumps"); public static final OptionKey<String> DumpPath = new OptionKey<>("graal_dumps");
@Option(help = "Print the name of each dump file path as it's created.") @Option(help = "Print the name of each dump file path as it's created.")
public static final OptionKey<Boolean> ShowDumpFiles = new OptionKey<>(false); public static final OptionKey<Boolean> ShowDumpFiles = new OptionKey<>(false);
@ -127,15 +136,30 @@ public class DebugOptions {
@Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug) @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug)
public static final OptionKey<Boolean> PrintBackendCFG = new OptionKey<>(true); public static final OptionKey<Boolean> PrintBackendCFG = new OptionKey<>(true);
@Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug) @Option(help = "file:doc-files/PrintGraphHelp.txt", type = OptionType.Debug)
public static final OptionKey<Boolean> PrintGraph = new OptionKey<>(true); public static final EnumOptionKey<PrintGraphTarget> PrintGraph = new EnumOptionKey<>(PrintGraphTarget.File);
@Option(help = "Print graphs to files instead of sending them over the network.", type = OptionType.Debug)
public static final OptionKey<Boolean> PrintGraphFile = new OptionKey<>(false); @Option(help = "Setting to true sets PrintGraph=file, setting to false sets PrintGraph=network", type = OptionType.Debug)
public static final OptionKey<Boolean> PrintGraphFile = new OptionKey<Boolean>(true) {
@Override
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean oldValue, Boolean newValue) {
PrintGraphTarget v = PrintGraph.getValueOrDefault(values);
if (newValue.booleanValue()) {
if (v != PrintGraphTarget.File) {
PrintGraph.update(values, PrintGraphTarget.File);
}
} else {
if (v != PrintGraphTarget.Network) {
PrintGraph.update(values, PrintGraphTarget.Network);
}
}
}
};
@Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug) @Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug)
public static final OptionKey<String> PrintGraphHost = new OptionKey<>("127.0.0.1"); public static final OptionKey<String> PrintGraphHost = new OptionKey<>("127.0.0.1");
@Option(help = "Port part of the address to which graphs are dumped in binary format.", type = OptionType.Debug) @Option(help = "Port part of the address to which graphs are dumped in binary format.", type = OptionType.Debug)
public static final OptionKey<Integer> PrintBinaryGraphPort = new OptionKey<>(4445); public static final OptionKey<Integer> PrintGraphPort = new OptionKey<>(4445);
@Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug) @Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug)
public static final OptionKey<Boolean> PrintGraphWithSchedule = new OptionKey<>(false); public static final OptionKey<Boolean> PrintGraphWithSchedule = new OptionKey<>(false);

View File

@ -24,6 +24,10 @@
package org.graalvm.compiler.debug; package org.graalvm.compiler.debug;
import static org.graalvm.compiler.debug.DebugOptions.PrintGraphHost;
import static org.graalvm.compiler.debug.DebugOptions.PrintGraphPort;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InterruptedIOException; import java.io.InterruptedIOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
@ -35,10 +39,12 @@ import java.nio.channels.WritableByteChannel;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.util.function.Supplier; import java.util.function.Supplier;
import static org.graalvm.compiler.debug.DebugOptions.PrintBinaryGraphPort;
import static org.graalvm.compiler.debug.DebugOptions.PrintGraphHost; import org.graalvm.compiler.debug.DebugOptions.PrintGraphTarget;
import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.common.NativeImageReinitialize;
final class IgvDumpChannel implements WritableByteChannel { final class IgvDumpChannel implements WritableByteChannel {
private final Supplier<Path> pathProvider; private final Supplier<Path> pathProvider;
private final OptionValues options; private final OptionValues options;
@ -52,7 +58,8 @@ final class IgvDumpChannel implements WritableByteChannel {
@Override @Override
public int write(ByteBuffer src) throws IOException { public int write(ByteBuffer src) throws IOException {
return channel().write(src); WritableByteChannel channel = channel();
return channel == null ? 0 : channel.write(src);
} }
@Override @Override
@ -77,10 +84,13 @@ final class IgvDumpChannel implements WritableByteChannel {
throw new IOException(); throw new IOException();
} }
if (sharedChannel == null) { if (sharedChannel == null) {
if (DebugOptions.PrintGraphFile.getValue(options)) { PrintGraphTarget target = DebugOptions.PrintGraph.getValue(options);
sharedChannel = createFileChannel(pathProvider); if (target == PrintGraphTarget.File) {
} else { sharedChannel = createFileChannel(pathProvider, null);
} else if (target == PrintGraphTarget.Network) {
sharedChannel = createNetworkChannel(pathProvider, options); sharedChannel = createNetworkChannel(pathProvider, options);
} else {
TTY.println("WARNING: Graph dumping requested but value of %s option is %s", DebugOptions.PrintGraph.getName(), PrintGraphTarget.Disable);
} }
} }
return sharedChannel; return sharedChannel;
@ -88,10 +98,11 @@ final class IgvDumpChannel implements WritableByteChannel {
private static WritableByteChannel createNetworkChannel(Supplier<Path> pathProvider, OptionValues options) throws IOException { private static WritableByteChannel createNetworkChannel(Supplier<Path> pathProvider, OptionValues options) throws IOException {
String host = PrintGraphHost.getValue(options); String host = PrintGraphHost.getValue(options);
int port = PrintBinaryGraphPort.getValue(options); int port = PrintGraphPort.getValue(options);
try { try {
WritableByteChannel channel = SocketChannel.open(new InetSocketAddress(host, port)); WritableByteChannel channel = SocketChannel.open(new InetSocketAddress(host, port));
TTY.println("Connected to the IGV on %s:%d", host, port); String targetAnnouncement = String.format("Connected to the IGV on %s:%d", host, port);
maybeAnnounceTarget(targetAnnouncement);
return channel; return channel;
} catch (ClosedByInterruptException | InterruptedIOException e) { } catch (ClosedByInterruptException | InterruptedIOException e) {
/* /*
@ -101,18 +112,39 @@ final class IgvDumpChannel implements WritableByteChannel {
*/ */
return null; return null;
} catch (IOException e) { } catch (IOException e) {
if (!DebugOptions.PrintGraphFile.hasBeenSet(options)) { String networkFailure = String.format("Could not connect to the IGV on %s:%d", host, port);
return createFileChannel(pathProvider); if (pathProvider != null) {
return createFileChannel(pathProvider, networkFailure);
} else { } else {
throw new IOException(String.format("Could not connect to the IGV on %s:%d", host, port), e); throw new IOException(networkFailure, e);
} }
} }
} }
private static WritableByteChannel createFileChannel(Supplier<Path> pathProvider) throws IOException { @NativeImageReinitialize private static String lastTargetAnnouncement;
private static void maybeAnnounceTarget(String targetAnnouncement) {
if (!targetAnnouncement.equals(lastTargetAnnouncement)) {
// Ignore races - an extra announcement is ok
lastTargetAnnouncement = targetAnnouncement;
TTY.println(targetAnnouncement);
}
}
private static WritableByteChannel createFileChannel(Supplier<Path> pathProvider, String networkFailure) throws IOException {
Path path = pathProvider.get(); Path path = pathProvider.get();
try { try {
return FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE); FileChannel channel = FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
File dir = path.toFile();
if (!dir.isDirectory()) {
dir = dir.getParentFile();
}
if (networkFailure == null) {
maybeAnnounceTarget("Dumping IGV graphs in " + dir);
} else {
maybeAnnounceTarget(networkFailure + ". Dumping IGV graphs in " + dir);
}
return channel;
} catch (IOException e) { } catch (IOException e) {
throw new IOException(String.format("Failed to open %s to dump IGV graphs", path), e); throw new IOException(String.format("Failed to open %s to dump IGV graphs", path), e);
} }

View File

@ -84,7 +84,7 @@ public class PathUtilities {
private static final String ELLIPSIS = "..."; private static final String ELLIPSIS = "...";
static Path createUnique(OptionValues options, OptionKey<String> baseNameOption, String id, String label, String ext, boolean createDirectory) throws IOException { static Path createUnique(OptionValues options, OptionKey<String> baseNameOption, String id, String label, String ext, boolean createMissingDirectory) throws IOException {
String uniqueTag = ""; String uniqueTag = "";
int dumpCounter = 1; int dumpCounter = 1;
String prefix; String prefix;
@ -118,7 +118,7 @@ public class PathUtilities {
Path dumpDir = DebugOptions.getDumpDirectory(options); Path dumpDir = DebugOptions.getDumpDirectory(options);
Path result = Paths.get(dumpDir.toString(), fileName); Path result = Paths.get(dumpDir.toString(), fileName);
try { try {
if (createDirectory) { if (createMissingDirectory) {
return Files.createDirectory(result); return Files.createDirectory(result);
} else { } else {
try { try {

View File

@ -0,0 +1,6 @@
Where IdealGraphVisualizer graph dumps triggered by Dump or DumpOnError should be written.
The accepted values are:
File - Dump IGV graphs to the local file system (see DumpPath).
Network - Dump IGV graphs to the network destination specified by PrintGraphHost and PrintGraphPort.
If a network connection cannot be opened, dumping falls back to file dumping.
Disable - Do not dump IGV graphs.

View File

@ -0,0 +1,284 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.graph.test.graphio;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import org.graalvm.graphio.GraphOutput;
import org.graalvm.graphio.GraphStructure;
import org.junit.Test;
public final class GraphOutputTest {
@Test
@SuppressWarnings("static-method")
public void testWritableByteChannel() throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
WritableByteChannel channel = Channels.newChannel(out);
ByteBuffer data = generateData(1 << 17);
GraphOutput<?, ?> graphOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).embedded(true).build(channel);
try (GraphOutput<?, ?> closable = graphOutput) {
assertTrue(closable.isOpen());
closable.write(data);
}
assertFalse(graphOutput.isOpen());
assertArrayEquals(data.array(), out.toByteArray());
}
@Test
@SuppressWarnings("static-method")
public void testWriteDuringPrint() throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
WritableByteChannel channel = Channels.newChannel(out);
class Action implements Runnable {
GraphOutput<MockGraph, ?> out;
@Override
public void run() {
try {
ByteBuffer data = ByteBuffer.allocate(16);
data.limit(16);
out.write(data);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
}
Action action = new Action();
try (GraphOutput<MockGraph, ?> graphOutput = GraphOutput.newBuilder(new MockGraphStructure(action)).protocolVersion(6, 0).build(channel)) {
action.out = graphOutput;
try {
graphOutput.print(new MockGraph(), Collections.emptyMap(), 0, "Mock Graph");
fail("Expected IllegalStateException");
} catch (IllegalStateException ise) {
// expected exception
}
}
}
@Test
@SuppressWarnings("static-method")
public void testEmbeddedWritableByteChannel() throws IOException {
ByteArrayOutputStream expected = new ByteArrayOutputStream();
WritableByteChannel expectedChannel = Channels.newChannel(expected);
Map<Object, Object> properties = Collections.singletonMap("version.id", 1);
try (GraphOutput<MockGraph, ?> graphOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).build(expectedChannel)) {
graphOutput.print(new MockGraph(), properties, 1, "Graph 1");
graphOutput.write(ByteBuffer.allocate(0));
graphOutput.print(new MockGraph(), properties, 2, "Graph 1");
}
ByteArrayOutputStream embedded = new ByteArrayOutputStream();
SharedWritableByteChannel embeddChannel = new SharedWritableByteChannel(Channels.newChannel(embedded));
try {
try (GraphOutput<MockGraph, ?> baseOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).build(embeddChannel)) {
try (GraphOutput<MockGraph, ?> embeddedOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).embedded(true).build((WritableByteChannel) baseOutput)) {
embeddedOutput.print(new MockGraph(), properties, 1, "Graph 1");
baseOutput.print(new MockGraph(), properties, 2, "Graph 1");
}
}
} finally {
embeddChannel.realClose();
}
assertArrayEquals(expected.toByteArray(), embedded.toByteArray());
}
private static ByteBuffer generateData(int size) {
ByteBuffer buffer = ByteBuffer.allocate(size);
for (int i = 0; i < size; i++) {
buffer.put(i, (byte) i);
}
buffer.limit(size);
return buffer;
}
private static final class SharedWritableByteChannel implements WritableByteChannel {
private final WritableByteChannel delegate;
SharedWritableByteChannel(WritableByteChannel delegate) {
Objects.requireNonNull(delegate, "Delegate must be non null.");
this.delegate = delegate;
}
@Override
public int write(ByteBuffer bb) throws IOException {
return delegate.write(bb);
}
@Override
public boolean isOpen() {
return delegate.isOpen();
}
@Override
public void close() throws IOException {
}
void realClose() throws IOException {
delegate.close();
}
}
private static final class MockGraphStructure implements GraphStructure<MockGraph, Void, Void, Void> {
private final Runnable enterAction;
MockGraphStructure() {
this.enterAction = null;
}
MockGraphStructure(Runnable enterAction) {
this.enterAction = enterAction;
}
@Override
public MockGraph graph(MockGraph currentGraph, Object obj) {
onEnter();
return null;
}
@Override
public Iterable<? extends Void> nodes(MockGraph graph) {
onEnter();
return Collections.emptySet();
}
@Override
public int nodesCount(MockGraph graph) {
onEnter();
return 0;
}
@Override
public int nodeId(Void node) {
onEnter();
return 0;
}
@Override
public boolean nodeHasPredecessor(Void node) {
onEnter();
return false;
}
@Override
public void nodeProperties(MockGraph graph, Void node, Map<String, ? super Object> properties) {
onEnter();
}
@Override
public Void node(Object obj) {
onEnter();
return null;
}
@Override
public Void nodeClass(Object obj) {
onEnter();
return null;
}
@Override
public Void classForNode(Void node) {
onEnter();
return null;
}
@Override
public String nameTemplate(Void nodeClass) {
onEnter();
return null;
}
@Override
public Object nodeClassType(Void nodeClass) {
onEnter();
return null;
}
@Override
public Void portInputs(Void nodeClass) {
onEnter();
return null;
}
@Override
public Void portOutputs(Void nodeClass) {
onEnter();
return null;
}
@Override
public int portSize(Void port) {
onEnter();
return 0;
}
@Override
public boolean edgeDirect(Void port, int index) {
onEnter();
return false;
}
@Override
public String edgeName(Void port, int index) {
onEnter();
return null;
}
@Override
public Object edgeType(Void port, int index) {
onEnter();
return null;
}
@Override
public Collection<? extends Void> edgeNodes(MockGraph graph, Void node, Void port, int index) {
onEnter();
return null;
}
private void onEnter() {
if (enterAction != null) {
enterAction.run();
}
}
}
private static final class MockGraph {
}
}

View File

@ -24,9 +24,7 @@
package org.graalvm.compiler.graph; package org.graalvm.compiler.graph;
import static org.graalvm.compiler.core.common.Fields.translateInto;
import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere; import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere;
import static org.graalvm.compiler.graph.Edges.translateInto;
import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled; import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled;
import static org.graalvm.compiler.graph.InputEdges.translateInto; import static org.graalvm.compiler.graph.InputEdges.translateInto;
import static org.graalvm.compiler.graph.Node.WithAllEdges; import static org.graalvm.compiler.graph.Node.WithAllEdges;

View File

@ -36,6 +36,7 @@ import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntr
import jdk.internal.vm.compiler.collections.EconomicSet; import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException;
import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64Address;
import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
@ -47,6 +48,7 @@ import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
import org.graalvm.compiler.core.gen.LIRGenerationProvider;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotDataBuilder; import org.graalvm.compiler.hotspot.HotSpotDataBuilder;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
@ -86,21 +88,16 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
/** /**
* HotSpot AArch64 specific backend. * HotSpot AArch64 specific backend.
*/ */
public class AArch64HotSpotBackend extends HotSpotHostBackend { public class AArch64HotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider {
public AArch64HotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) { public AArch64HotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
super(config, runtime, providers); super(config, runtime, providers);
} }
@Override private FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
return new AArch64FrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull); FrameMap frameMap = new AArch64FrameMap(getCodeCache(), registerConfigNonNull, this);
} return new AArch64FrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull);
@Override
public FrameMap newFrameMap(RegisterConfig registerConfig) {
return new AArch64FrameMap(getCodeCache(), registerConfig, this);
} }
@Override @Override
@ -109,8 +106,9 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend {
} }
@Override @Override
public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, Object stub) { public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, Object stub) {
return new HotSpotLIRGenerationResult(compilationId, lir, frameMapBuilder, makeCallingConvention(graph, (Stub) stub), stub, config.requiresReservedStackCheck(graph.getMethods())); return new HotSpotLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerConfig), makeCallingConvention(graph, (Stub) stub), stub,
config.requiresReservedStackCheck(graph.getMethods()));
} }
@Override @Override
@ -218,11 +216,6 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend {
} }
@Override
protected Assembler createAssembler(FrameMap frameMap) {
return new AArch64MacroAssembler(getTarget());
}
@Override @Override
public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRen; HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRen;
@ -230,7 +223,7 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend {
assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
Stub stub = gen.getStub(); Stub stub = gen.getStub();
Assembler masm = createAssembler(frameMap); Assembler masm = new AArch64MacroAssembler(getTarget());
HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null);
DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget());
@ -252,11 +245,25 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend {
@Override @Override
public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) { public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) {
Label verifiedStub = new Label();
crb.buildLabelOffsets(lir);
try {
emitCode(crb, lir, installedCodeOwner, verifiedStub);
} catch (BranchTargetOutOfBoundsException e) {
// A branch estimation was wrong, now retry with conservative label ranges, this
// should always work
crb.setConservativeLabelRanges();
crb.resetForEmittingCode();
lir.resetLabels();
verifiedStub.reset();
emitCode(crb, lir, installedCodeOwner, verifiedStub);
}
}
private void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner, Label verifiedStub) {
AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm; AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm;
FrameMap frameMap = crb.frameMap; FrameMap frameMap = crb.frameMap;
RegisterConfig regConfig = frameMap.getRegisterConfig(); RegisterConfig regConfig = frameMap.getRegisterConfig();
Label verifiedStub = new Label();
emitCodePrefix(crb, installedCodeOwner, masm, regConfig, verifiedStub); emitCodePrefix(crb, installedCodeOwner, masm, regConfig, verifiedStub);
emitCodeBody(crb, lir, masm); emitCodeBody(crb, lir, masm);
emitCodeSuffix(crb, masm, frameMap); emitCodeSuffix(crb, masm, frameMap);

View File

@ -37,7 +37,7 @@ import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.Opcode;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.serviceprovider.GraalServices; import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import jdk.vm.ci.code.Register; import jdk.vm.ci.code.Register;
import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.AllocatableValue;
@ -71,7 +71,7 @@ public class AArch64HotSpotJumpToExceptionHandlerInCallerOp extends AArch64HotSp
public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
leaveFrame(crb, masm, /* emitSafepoint */false, false); leaveFrame(crb, masm, /* emitSafepoint */false, false);
if (GraalServices.JAVA_SPECIFICATION_VERSION < 8) { if (JavaVersionUtil.JAVA_SPECIFICATION_VERSION < 8) {
// Restore sp from fp if the exception PC is a method handle call site. // Restore sp from fp if the exception PC is a method handle call site.
try (ScratchRegister sc = masm.getScratchRegister()) { try (ScratchRegister sc = masm.getScratchRegister()) {
Register scratch = sc.getRegister(); Register scratch = sc.getRegister();

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.amd64.test;
import static org.junit.Assume.assumeTrue;
import java.util.ArrayList;
import java.util.List;
import org.graalvm.compiler.api.test.Graal;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.runtime.RuntimeProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.code.Architecture;
@RunWith(Parameterized.class)
public class BinaryMathStubTest extends GraalCompilerTest {
@Parameterized.Parameters(name = "{0}")
public static List<Object[]> data() {
ArrayList<Object[]> ret = new ArrayList<>();
ret.add(new Object[]{"pow"});
return ret;
}
private static final double[] inputs = {0.0D, Math.PI / 2, Math.PI, -1.0D, Double.MAX_VALUE, Double.MIN_VALUE, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY};
private final String stub;
public BinaryMathStubTest(String stub) {
this.stub = stub;
}
@Before
public void checkAMD64() {
Architecture arch = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget().arch;
assumeTrue("skipping AMD64 specific test", arch instanceof AMD64);
}
public static double pow(double x, double y) {
return Math.pow(x, y);
}
@Test
public void testStub() {
for (double x : inputs) {
for (double y : inputs) {
test(stub, x, y);
}
}
}
}

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.amd64.test;
import static org.junit.Assume.assumeTrue;
import java.util.ArrayList;
import java.util.List;
import org.graalvm.compiler.api.test.Graal;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.runtime.RuntimeProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.code.Architecture;
@RunWith(Parameterized.class)
public class UnaryMathStubTest extends GraalCompilerTest {
@Parameterized.Parameters(name = "{0}")
public static List<Object[]> data() {
ArrayList<Object[]> ret = new ArrayList<>();
ret.add(new Object[]{"sin"});
ret.add(new Object[]{"cos"});
ret.add(new Object[]{"tan"});
ret.add(new Object[]{"exp"});
ret.add(new Object[]{"log"});
ret.add(new Object[]{"log10"});
return ret;
}
private static final double[] inputs = {0.0D, Math.PI / 2, Math.PI, -1.0D, Double.MAX_VALUE, Double.MIN_VALUE, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY};
private final String stub;
public UnaryMathStubTest(String stub) {
this.stub = stub;
}
@Before
public void checkAMD64() {
Architecture arch = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget().arch;
assumeTrue("skipping AMD64 specific test", arch instanceof AMD64);
}
public static double sin(double value) {
return Math.sin(value);
}
public static double cos(double value) {
return Math.cos(value);
}
public static double tan(double value) {
return Math.tan(value);
}
public static double exp(double value) {
return Math.exp(value);
}
public static double log(double value) {
return Math.log(value);
}
public static double log10(double value) {
return Math.log10(value);
}
@Test
public void testStub() {
for (double input : inputs) {
test(stub, input);
}
}
}

View File

@ -199,7 +199,7 @@ public class AMD64HotSpotAddressLowering extends AMD64CompressAddressLowering {
CountedLoopInfo countedLoopInfo = loop.counted(); CountedLoopInfo countedLoopInfo = loop.counted();
IntegerStamp initStamp = (IntegerStamp) inductionVariable.initNode().stamp(NodeView.DEFAULT); IntegerStamp initStamp = (IntegerStamp) inductionVariable.initNode().stamp(NodeView.DEFAULT);
if (initStamp.isPositive()) { if (initStamp.isPositive()) {
if (inductionVariable.isConstantExtremum()) { if (inductionVariable.isConstantExtremum() && countedLoopInfo.counterNeverOverflows()) {
long init = inductionVariable.constantInit(); long init = inductionVariable.constantInit();
long stride = inductionVariable.constantStride(); long stride = inductionVariable.constantStride();
long extremum = inductionVariable.constantExtremum(); long extremum = inductionVariable.constantExtremum();
@ -211,7 +211,9 @@ public class AMD64HotSpotAddressLowering extends AMD64CompressAddressLowering {
} }
} }
} }
if (countedLoopInfo.getCounter() == inductionVariable && inductionVariable.direction() == InductionVariable.Direction.Up && countedLoopInfo.getOverFlowGuard() != null) { if (countedLoopInfo.getCounter() == inductionVariable &&
inductionVariable.direction() == InductionVariable.Direction.Up &&
(countedLoopInfo.getOverFlowGuard() != null || countedLoopInfo.counterNeverOverflows())) {
return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true)); return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true));
} }
} }

View File

@ -43,7 +43,7 @@ import org.graalvm.compiler.core.amd64.AMD64NodeMatchRules;
import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.core.gen.LIRGenerationProvider;
import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotDataBuilder; import org.graalvm.compiler.hotspot.HotSpotDataBuilder;
@ -85,21 +85,16 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
/** /**
* HotSpot AMD64 specific backend. * HotSpot AMD64 specific backend.
*/ */
public class AMD64HotSpotBackend extends HotSpotHostBackend { public class AMD64HotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider {
public AMD64HotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) { public AMD64HotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
super(config, runtime, providers); super(config, runtime, providers);
} }
@Override private FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
return new AMD64FrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull); FrameMap frameMap = new AMD64FrameMap(getCodeCache(), registerConfigNonNull, this);
} return new AMD64FrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull);
@Override
public FrameMap newFrameMap(RegisterConfig registerConfig) {
return new AMD64FrameMap(getCodeCache(), registerConfig, this);
} }
@Override @Override
@ -108,8 +103,9 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend {
} }
@Override @Override
public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, Object stub) { public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, Object stub) {
return new HotSpotLIRGenerationResult(compilationId, lir, frameMapBuilder, makeCallingConvention(graph, (Stub) stub), stub, config.requiresReservedStackCheck(graph.getMethods())); return new HotSpotLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerConfig), makeCallingConvention(graph, (Stub) stub), stub,
config.requiresReservedStackCheck(graph.getMethods()));
} }
@Override @Override
@ -195,11 +191,6 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend {
} }
} }
@Override
protected Assembler createAssembler(FrameMap frameMap) {
return new AMD64MacroAssembler(getTarget());
}
@Override @Override
public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
// Omit the frame if the method: // Omit the frame if the method:
@ -216,7 +207,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend {
boolean omitFrame = CanOmitFrame.getValue(options) && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall(); boolean omitFrame = CanOmitFrame.getValue(options) && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall();
Stub stub = gen.getStub(); Stub stub = gen.getStub();
Assembler masm = createAssembler(frameMap); Assembler masm = new AMD64MacroAssembler(getTarget());
HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame); HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame);
DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget());
CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, debug, compilationResult, Register.None); CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, debug, compilationResult, Register.None);
@ -258,7 +249,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend {
/** /**
* Emits the code prior to the verified entry point. * Emits the code prior to the verified entry point.
* *
* @param installedCodeOwner see {@link Backend#emitCode} * @param installedCodeOwner see {@link LIRGenerationProvider#emitCode}
*/ */
public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, RegisterConfig regConfig, Label verifiedEntry) { public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, RegisterConfig regConfig, Label verifiedEntry) {
HotSpotProviders providers = getProviders(); HotSpotProviders providers = getProviders();
@ -309,14 +300,14 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend {
/** /**
* Emits the code which starts at the verified entry point. * Emits the code which starts at the verified entry point.
* *
* @param installedCodeOwner see {@link Backend#emitCode} * @param installedCodeOwner see {@link LIRGenerationProvider#emitCode}
*/ */
public void emitCodeBody(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, LIR lir) { public void emitCodeBody(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, LIR lir) {
crb.emit(lir); crb.emit(lir);
} }
/** /**
* @param installedCodeOwner see {@link Backend#emitCode} * @param installedCodeOwner see {@link LIRGenerationProvider#emitCode}
*/ */
public void emitCodeSuffix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, FrameMap frameMap) { public void emitCodeSuffix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, FrameMap frameMap) {
HotSpotProviders providers = getProviders(); HotSpotProviders providers = getProviders();

View File

@ -25,7 +25,6 @@
package org.graalvm.compiler.hotspot.amd64; package org.graalvm.compiler.hotspot.amd64;
import static jdk.vm.ci.common.InitTimer.timer; import static jdk.vm.ci.common.InitTimer.timer;
import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -141,7 +140,7 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory {
replacements = createReplacements(options, p, snippetReflection, bytecodeProvider); replacements = createReplacements(options, p, snippetReflection, bytecodeProvider);
} }
try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
plugins = createGraphBuilderPlugins(compilerConfiguration, config, options, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes); plugins = createGraphBuilderPlugins(compilerConfiguration, config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes);
replacements.setGraphBuilderPlugins(plugins); replacements.setGraphBuilderPlugins(plugins);
} }
try (InitTimer rt = timer("create Suites provider")) { try (InitTimer rt = timer("create Suites provider")) {
@ -157,11 +156,11 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory {
} }
} }
protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, OptionValues options, TargetDescription target, protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, TargetDescription target,
HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess,
HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) { HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) {
Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements); Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements);
AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, GraalArithmeticStubs.getValue(options), false); AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false);
return plugins; return plugins;
} }

View File

@ -30,6 +30,7 @@ import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall;
import static jdk.vm.ci.meta.Value.ILLEGAL; import static jdk.vm.ci.meta.Value.ILLEGAL;
import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER;
import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER;
import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION;
@ -38,10 +39,16 @@ import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP;
import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C; import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32;
import static org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation.POW;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.COS;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.EXP;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
import static jdk.internal.vm.compiler.word.LocationIdentity.any; import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
@ -62,14 +69,6 @@ import jdk.vm.ci.meta.Value;
public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsProvider { public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsProvider {
public static final ForeignCallDescriptor ARITHMETIC_SIN_STUB = new ForeignCallDescriptor("arithmeticSinStub", double.class, double.class);
public static final ForeignCallDescriptor ARITHMETIC_COS_STUB = new ForeignCallDescriptor("arithmeticCosStub", double.class, double.class);
public static final ForeignCallDescriptor ARITHMETIC_TAN_STUB = new ForeignCallDescriptor("arithmeticTanStub", double.class, double.class);
public static final ForeignCallDescriptor ARITHMETIC_EXP_STUB = new ForeignCallDescriptor("arithmeticExpStub", double.class, double.class);
public static final ForeignCallDescriptor ARITHMETIC_POW_STUB = new ForeignCallDescriptor("arithmeticPowStub", double.class, double.class, double.class);
public static final ForeignCallDescriptor ARITHMETIC_LOG_STUB = new ForeignCallDescriptor("arithmeticLogStub", double.class, double.class);
public static final ForeignCallDescriptor ARITHMETIC_LOG10_STUB = new ForeignCallDescriptor("arithmeticLog10Stub", double.class, double.class);
private final Value[] nativeABICallerSaveRegisters; private final Value[] nativeABICallerSaveRegisters;
public AMD64HotSpotForeignCallsProvider(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache, public AMD64HotSpotForeignCallsProvider(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache,
@ -93,14 +92,6 @@ public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro
register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any())); register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any()));
register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any())); register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any()));
link(new AMD64MathStub(ARITHMETIC_LOG_STUB, options, providers, registerStubCall(ARITHMETIC_LOG_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64MathStub(ARITHMETIC_LOG10_STUB, options, providers, registerStubCall(ARITHMETIC_LOG10_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64MathStub(ARITHMETIC_SIN_STUB, options, providers, registerStubCall(ARITHMETIC_SIN_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64MathStub(ARITHMETIC_COS_STUB, options, providers, registerStubCall(ARITHMETIC_COS_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64MathStub(ARITHMETIC_TAN_STUB, options, providers, registerStubCall(ARITHMETIC_TAN_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64MathStub(ARITHMETIC_EXP_STUB, options, providers, registerStubCall(ARITHMETIC_EXP_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64MathStub(ARITHMETIC_POW_STUB, options, providers, registerStubCall(ARITHMETIC_POW_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
if (config.useCRC32Intrinsics) { if (config.useCRC32Intrinsics) {
// This stub does callee saving // This stub does callee saving
registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any()); registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
@ -138,4 +129,19 @@ public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro
return nativeABICallerSaveRegisters; return nativeABICallerSaveRegisters;
} }
@Override
protected void registerMathStubs(GraalHotSpotVMConfig hotSpotVMConfig, HotSpotProviders providers, OptionValues options) {
if (GraalArithmeticStubs.getValue(options)) {
link(new AMD64MathStub(SIN, options, providers, registerStubCall(SIN.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64MathStub(COS, options, providers, registerStubCall(COS.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64MathStub(TAN, options, providers, registerStubCall(TAN.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64MathStub(EXP, options, providers, registerStubCall(EXP.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64MathStub(LOG, options, providers, registerStubCall(LOG.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64MathStub(LOG10, options, providers, registerStubCall(LOG10.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64MathStub(POW, options, providers, registerStubCall(POW.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
} else {
super.registerMathStubs(hotSpotVMConfig, providers, options);
}
}
} }

View File

@ -24,10 +24,10 @@
package org.graalvm.compiler.hotspot.amd64; package org.graalvm.compiler.hotspot.amd64;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static jdk.vm.ci.amd64.AMD64.rbp; import static jdk.vm.ci.amd64.AMD64.rbp;
import static jdk.vm.ci.amd64.AMD64.rsp; import static jdk.vm.ci.amd64.AMD64.rsp;
import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.asRegister;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
@ -35,7 +35,7 @@ import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.Opcode;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.serviceprovider.GraalServices; import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import jdk.vm.ci.code.Register; import jdk.vm.ci.code.Register;
import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.AllocatableValue;
@ -71,7 +71,7 @@ final class AMD64HotSpotJumpToExceptionHandlerInCallerOp extends AMD64HotSpotEpi
// Discard the return address, thus completing restoration of caller frame // Discard the return address, thus completing restoration of caller frame
masm.incrementq(rsp, 8); masm.incrementq(rsp, 8);
if (GraalServices.JAVA_SPECIFICATION_VERSION < 8) { if (JavaVersionUtil.JAVA_SPECIFICATION_VERSION < 8) {
// Restore rsp from rbp if the exception PC is a method handle call site. // Restore rsp from rbp if the exception PC is a method handle call site.
AMD64Address dst = new AMD64Address(thread, isMethodHandleReturnOffset); AMD64Address dst = new AMD64Address(thread, isMethodHandleReturnOffset);
masm.cmpl(dst, 0); masm.cmpl(dst, 0);

View File

@ -118,7 +118,7 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp
} }
private AMD64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, BackupSlotProvider backupSlotProvider) { private AMD64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, BackupSlotProvider backupSlotProvider) {
this(new AMD64HotSpotLIRKindTool(), new AMD64ArithmeticLIRGenerator(null, new AMD64HotSpotMaths()), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes); this(new AMD64HotSpotLIRKindTool(), new AMD64ArithmeticLIRGenerator(null), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes);
} }
protected AMD64HotSpotLIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config, protected AMD64HotSpotLIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config,

View File

@ -25,15 +25,8 @@
package org.graalvm.compiler.hotspot.amd64; package org.graalvm.compiler.hotspot.amd64;
import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_COS_STUB;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_EXP_STUB;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG10_STUB;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG_STUB;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_POW_STUB;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_SIN_STUB;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_TAN_STUB;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.Node;
@ -44,21 +37,26 @@ import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode;
import org.graalvm.compiler.hotspot.replacements.profiling.ProbabilisticProfileSnippets; import org.graalvm.compiler.hotspot.replacements.profiling.ProbabilisticProfileSnippets;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.calc.FloatConvertNode; import org.graalvm.compiler.nodes.calc.FloatConvertNode;
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.replacements.amd64.AMD64ConvertSnippets; import org.graalvm.compiler.replacements.amd64.AMD64ConvertSnippets;
import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider { public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider {
private AMD64ConvertSnippets.Templates convertSnippets; private AMD64ConvertSnippets.Templates convertSnippets;
private ProbabilisticProfileSnippets.Templates profileSnippets; private ProbabilisticProfileSnippets.Templates profileSnippets;
private AMD64X87MathSnippets.Templates mathSnippets;
public AMD64HotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, public AMD64HotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers,
HotSpotConstantReflectionProvider constantReflection, TargetDescription target) { HotSpotConstantReflectionProvider constantReflection, TargetDescription target) {
@ -68,9 +66,10 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider
@Override @Override
public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, GraalHotSpotVMConfig config) { public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, GraalHotSpotVMConfig config) {
convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) && !JavaVersionUtil.Java8OrEarlier
? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget()) ? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget())
: null; : null;
mathSnippets = new AMD64X87MathSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
super.initialize(options, factories, providers, config); super.initialize(options, factories, providers, config);
} }
@ -80,47 +79,49 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider
convertSnippets.lower((FloatConvertNode) n, tool); convertSnippets.lower((FloatConvertNode) n, tool);
} else if (profileSnippets != null && n instanceof ProfileNode) { } else if (profileSnippets != null && n instanceof ProfileNode) {
profileSnippets.lower((ProfileNode) n, tool); profileSnippets.lower((ProfileNode) n, tool);
} else if (n instanceof UnaryMathIntrinsicNode) {
lowerUnaryMath((UnaryMathIntrinsicNode) n, tool);
} else { } else {
super.lower(n, tool); super.lower(n, tool);
} }
} }
@Override private void lowerUnaryMath(UnaryMathIntrinsicNode math, LoweringTool tool) {
protected ForeignCallDescriptor toForeignCall(UnaryOperation operation) { if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) {
if (GraalArithmeticStubs.getValue(runtime.getOptions())) { return;
switch (operation) { }
case LOG: StructuredGraph graph = math.graph();
return ARITHMETIC_LOG_STUB; ResolvedJavaMethod method = graph.method();
case LOG10: if (method != null) {
return ARITHMETIC_LOG10_STUB; if (method.getAnnotation(Snippet.class) != null) {
// In the context of SnippetStub, i.e., Graal-generated stubs, use the LIR
// lowering to emit the stub assembly code instead of the Node lowering.
return;
}
}
if (!GraalArithmeticStubs.getValue(graph.getOptions())) {
switch (math.getOperation()) {
case SIN: case SIN:
return ARITHMETIC_SIN_STUB;
case COS: case COS:
return ARITHMETIC_COS_STUB;
case TAN: case TAN:
return ARITHMETIC_TAN_STUB; // Math.sin(), .cos() and .tan() guarantee a value within 1 ULP of the exact
case EXP: // result, but x87 trigonometric FPU instructions are only that accurate within
return ARITHMETIC_EXP_STUB; // [-pi/4, pi/4]. The snippets fall back to a foreign call to HotSpot stubs
// should the inputs outside of that interval.
mathSnippets.lower(math, tool);
return;
case LOG:
math.replaceAtUsages(graph.addOrUnique(new AMD64X87MathIntrinsicNode(math.getValue(), UnaryOperation.LOG)));
return;
case LOG10:
math.replaceAtUsages(graph.addOrUnique(new AMD64X87MathIntrinsicNode(math.getValue(), UnaryOperation.LOG10)));
return;
} }
} else if (operation == UnaryOperation.EXP) {
return operation.foreignCallDescriptor;
} }
// Lower only using LIRGenerator
return null;
}
@Override ForeignCallNode call = graph.add(new ForeignCallNode(foreignCalls, math.getOperation().foreignCallDescriptor, math.getValue()));
protected ForeignCallDescriptor toForeignCall(BinaryOperation operation) { graph.addAfterFixed(tool.lastFixedNode(), call);
if (GraalArithmeticStubs.getValue(runtime.getOptions())) { math.replaceAtUsages(call);
switch (operation) {
case POW:
return ARITHMETIC_POW_STUB;
}
} else if (operation == BinaryOperation.POW) {
return operation.foreignCallDescriptor;
}
// Lower only using LIRGenerator
return null;
} }
@Override @Override

View File

@ -1,88 +0,0 @@
/*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.amd64;
import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.COS;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG10;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.SIN;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.TAN;
import org.graalvm.compiler.core.amd64.AMD64ArithmeticLIRGenerator;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.hotspot.HotSpotBackend.Options;
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.gen.LIRGenerator;
import jdk.vm.ci.meta.Value;
/**
* Lowering of selected {@link Math} routines that depends on the value of
* {@link Options#GraalArithmeticStubs}.
*/
public class AMD64HotSpotMaths implements AMD64ArithmeticLIRGenerator.Maths {
@Override
public Variable emitLog(LIRGenerator gen, Value input, boolean base10) {
if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) {
return null;
}
Variable result = gen.newVariable(LIRKind.combine(input));
gen.append(new AMD64HotSpotMathIntrinsicOp(base10 ? LOG10 : LOG, result, gen.asAllocatable(input)));
return result;
}
@Override
public Variable emitCos(LIRGenerator gen, Value input) {
if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) {
return null;
}
Variable result = gen.newVariable(LIRKind.combine(input));
gen.append(new AMD64HotSpotMathIntrinsicOp(COS, result, gen.asAllocatable(input)));
return result;
}
@Override
public Variable emitSin(LIRGenerator gen, Value input) {
if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) {
return null;
}
Variable result = gen.newVariable(LIRKind.combine(input));
gen.append(new AMD64HotSpotMathIntrinsicOp(SIN, result, gen.asAllocatable(input)));
return result;
}
@Override
public Variable emitTan(LIRGenerator gen, Value input) {
if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) {
return null;
}
Variable result = gen.newVariable(LIRKind.combine(input));
gen.append(new AMD64HotSpotMathIntrinsicOp(TAN, result, gen.asAllocatable(input)));
return result;
}
}

View File

@ -24,16 +24,8 @@
package org.graalvm.compiler.hotspot.amd64; package org.graalvm.compiler.hotspot.amd64;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_COS_STUB;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_EXP_STUB;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG10_STUB;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG_STUB;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_POW_STUB;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_SIN_STUB;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_TAN_STUB;
import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.hotspot.stubs.SnippetStub; import org.graalvm.compiler.hotspot.stubs.SnippetStub;
@ -48,33 +40,38 @@ import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOpera
*/ */
public class AMD64MathStub extends SnippetStub { public class AMD64MathStub extends SnippetStub {
public AMD64MathStub(ForeignCallDescriptor descriptor, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { public AMD64MathStub(UnaryOperation operation, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
super(snippetName(descriptor), options, providers, linkage); super(snippetName(operation), options, providers, linkage);
} }
private static String snippetName(ForeignCallDescriptor descriptor) { public AMD64MathStub(BinaryOperation operation, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
if (descriptor == ARITHMETIC_LOG_STUB) { super(snippetName(operation), options, providers, linkage);
return "log"; }
private static String snippetName(UnaryOperation operation) {
switch (operation) {
case SIN:
return "sin";
case COS:
return "cos";
case TAN:
return "tan";
case EXP:
return "exp";
case LOG:
return "log";
case LOG10:
return "log10";
default:
throw GraalError.shouldNotReachHere("Unknown operation " + operation);
} }
if (descriptor == ARITHMETIC_LOG10_STUB) { }
return "log10";
} private static String snippetName(BinaryOperation operation) {
if (descriptor == ARITHMETIC_SIN_STUB) { if (operation == BinaryOperation.POW) {
return "sin";
}
if (descriptor == ARITHMETIC_COS_STUB) {
return "cos";
}
if (descriptor == ARITHMETIC_TAN_STUB) {
return "tan";
}
if (descriptor == ARITHMETIC_EXP_STUB) {
return "exp";
}
if (descriptor == ARITHMETIC_POW_STUB) {
return "pow"; return "pow";
} }
throw new InternalError("Unknown operation " + descriptor); throw GraalError.shouldNotReachHere("Unknown operation " + operation);
} }
@Snippet @Snippet

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.amd64;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.COS;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG10;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.SIN;
import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.TAN;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.type.FloatStamp;
import org.graalvm.compiler.core.common.type.PrimitiveStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.UnaryNode;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
import jdk.vm.ci.meta.Value;
@NodeInfo(nameTemplate = "X87MathIntrinsic#{p#operation/s}", cycles = CYCLES_64, size = SIZE_1)
public final class AMD64X87MathIntrinsicNode extends UnaryNode implements LIRLowerable {
public static final NodeClass<AMD64X87MathIntrinsicNode> TYPE = NodeClass.create(AMD64X87MathIntrinsicNode.class);
protected final UnaryOperation operation;
protected AMD64X87MathIntrinsicNode(ValueNode value, UnaryOperation op) {
super(TYPE, op.computeStamp(value.stamp(NodeView.DEFAULT)), value);
assert value.stamp(NodeView.DEFAULT) instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp(NodeView.DEFAULT)) == 64;
this.operation = op;
}
@Override
public Stamp foldStamp(Stamp valueStamp) {
return operation.computeStamp(valueStamp);
}
@Override
public void generate(NodeLIRBuilderTool generator) {
LIRGeneratorTool gen = generator.getLIRGeneratorTool();
Value input = generator.operand(getValue());
Variable result = gen.newVariable(LIRKind.combine(input));
switch (operation) {
case SIN:
gen.append(new AMD64HotSpotMathIntrinsicOp(SIN, result, gen.asAllocatable(input)));
break;
case COS:
gen.append(new AMD64HotSpotMathIntrinsicOp(COS, result, gen.asAllocatable(input)));
break;
case TAN:
gen.append(new AMD64HotSpotMathIntrinsicOp(TAN, result, gen.asAllocatable(input)));
break;
case LOG:
gen.append(new AMD64HotSpotMathIntrinsicOp(LOG, result, gen.asAllocatable(input)));
break;
case LOG10:
gen.append(new AMD64HotSpotMathIntrinsicOp(LOG10, result, gen.asAllocatable(input)));
break;
default:
throw GraalError.shouldNotReachHere();
}
generator.setResult(this, result);
}
@Override
public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
if (forValue.isConstant()) {
return ConstantNode.forDouble(operation.compute(forValue.asJavaConstant().asDouble()));
}
return this;
}
@NodeIntrinsic
public static native double compute(double value, @ConstantNodeParameter UnaryOperation op);
}

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.amd64;
import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
import org.graalvm.compiler.replacements.SnippetTemplate.Arguments;
import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
import org.graalvm.compiler.replacements.Snippets;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
import jdk.vm.ci.code.TargetDescription;
public class AMD64X87MathSnippets implements Snippets {
private static final double PI_4 = Math.PI / 4;
@Snippet
public static double sin(double input) {
if (Math.abs(input) < PI_4) {
return AMD64X87MathIntrinsicNode.compute(input, UnaryOperation.SIN);
}
return callDouble1(UnaryOperation.SIN.foreignCallDescriptor, input);
}
@Snippet
public static double cos(double input) {
if (Math.abs(input) < PI_4) {
return AMD64X87MathIntrinsicNode.compute(input, UnaryOperation.COS);
}
return callDouble1(UnaryOperation.COS.foreignCallDescriptor, input);
}
@Snippet
public static double tan(double input) {
if (Math.abs(input) < PI_4) {
return AMD64X87MathIntrinsicNode.compute(input, UnaryOperation.TAN);
}
return callDouble1(UnaryOperation.TAN.foreignCallDescriptor, input);
}
@NodeIntrinsic(value = ForeignCallNode.class)
private static native double callDouble1(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value);
public static class Templates extends AbstractTemplates {
private final SnippetInfo sin;
private final SnippetInfo cos;
private final SnippetInfo tan;
public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) {
super(options, factories, providers, snippetReflection, target);
sin = snippet(AMD64X87MathSnippets.class, "sin");
cos = snippet(AMD64X87MathSnippets.class, "cos");
tan = snippet(AMD64X87MathSnippets.class, "tan");
}
public void lower(UnaryMathIntrinsicNode mathIntrinsicNode, LoweringTool tool) {
SnippetInfo info;
switch (mathIntrinsicNode.getOperation()) {
case SIN:
info = sin;
break;
case COS:
info = cos;
break;
case TAN:
info = tan;
break;
default:
throw GraalError.shouldNotReachHere("Snippet not found for math intrinsic " + mathIntrinsicNode.getOperation().name());
}
Arguments args = new Arguments(info, mathIntrinsicNode.graph().getGuardsStage(), tool.getLoweringStage());
args.add("input", mathIntrinsicNode.getValue());
template(mathIntrinsicNode, args).instantiate(providers.getMetaAccess(), mathIntrinsicNode, DEFAULT_REPLACER, tool, args);
mathIntrinsicNode.safeDelete();
}
}
}

View File

@ -0,0 +1,142 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.jdk9.test;
import static org.junit.Assume.assumeFalse;
import jdk.vm.ci.code.InstalledCode;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.hotspot.replacements.StringUTF16Substitutions;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.java.NewArrayNode;
import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode;
import org.graalvm.compiler.replacements.test.MethodSubstitutionTest;
import org.graalvm.compiler.test.AddExports;
import org.junit.Before;
import org.junit.Test;
/**
* Test substitutions for (innate) methods StringUTF16.toBytes and StringUTF16.getChars provided by
* {@link StringUTF16Substitutions}.
*/
@AddExports({"java.base/java.lang"})
public final class StringUTF16ToBytesGetCharsTest extends MethodSubstitutionTest {
private static final int N = 1000;
private static final int N_OVERFLOW = 10;
@Before
public void checkAMD64() {
assumeFalse(Java8OrEarlier);
}
@Test
public void testStringUTF16ToBytes() throws ClassNotFoundException {
Class<?> javaclass = Class.forName("java.lang.StringUTF16");
ResolvedJavaMethod caller = getResolvedJavaMethod(javaclass, "toBytes", char[].class, int.class, int.class);
StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext());
assertInGraph(graph, NewArrayNode.class);
assertInGraph(graph, ArrayCopyCallNode.class);
InstalledCode code = getCode(caller, graph);
for (int srcOffset = 0; srcOffset < 2; srcOffset++) {
for (int i = 0; i < N; i++) {
int length = i2sz(i);
char[] src = fillUTF16Chars(new char[length]);
int copiedLength = Math.max(0, length - srcOffset);
int srcDelta = Math.min(srcOffset, copiedLength);
byte[] dst = (byte[]) invokeSafe(caller, null, src, srcDelta, copiedLength);
assert dst.length == copiedLength * 2;
byte[] dst2 = (byte[]) executeVarargsSafe(code, src, srcDelta, copiedLength);
assertDeepEquals(dst, dst2);
}
}
for (int srcOff = 0; srcOff < N_OVERFLOW; ++srcOff) {
for (int len = 0; len < N_OVERFLOW; ++len) {
char[] src = fillUTF16Chars(new char[N_OVERFLOW]);
test(caller, null, src, srcOff, len);
}
}
}
@Test
public void testStringUTF16getChars() throws ClassNotFoundException {
Class<?> javaclass = Class.forName("java.lang.StringUTF16");
ResolvedJavaMethod caller = getResolvedJavaMethod(javaclass, "getChars", byte[].class, int.class, int.class, char[].class, int.class);
StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext());
assertInGraph(graph, ArrayCopyCallNode.class);
InstalledCode code = getCode(caller, graph);
for (int dstOffset = 0; dstOffset < 2; dstOffset++) {
for (int srcOffset = 0; srcOffset < 2; srcOffset++) {
for (int i = 0; i < N; i++) {
int length = i2sz(i);
byte[] src = fillUTF16Bytes(new byte[length * 2]);
char[] dst = new char[length];
int copiedLength = Math.max(0, length - Math.max(dstOffset, srcOffset));
int dstDelta = Math.min(dstOffset, copiedLength);
int srcDelta = Math.min(srcOffset, copiedLength);
invokeSafe(caller, null, src, srcDelta, srcDelta + copiedLength, dst, dstDelta);
char[] dst2 = new char[length];
executeVarargsSafe(code, src, srcDelta, srcDelta + copiedLength, dst2, dstDelta);
assertDeepEquals(dst, dst2);
}
}
}
for (int srcOff = 0; srcOff < N_OVERFLOW; ++srcOff) {
for (int dstOff = 0; dstOff < N_OVERFLOW; ++dstOff) {
for (int len = 0; len < N_OVERFLOW; ++len) {
byte[] src = fillUTF16Bytes(new byte[N_OVERFLOW]);
char[] dst = new char[N_OVERFLOW];
test(caller, null, src, srcOff, len, dst, dstOff);
}
}
}
}
private static char[] fillUTF16Chars(char[] v) {
for (int ch = 0, i = 0; i < v.length; i++, ch += 0x101) {
v[i] = (char) ch;
}
return v;
}
private static byte[] fillUTF16Bytes(byte[] v) {
for (int ch = 1, i = 0; i < v.length; i += 2, ch++) {
v[i] = (byte) (ch - 1);
v[i + 1] = (byte) ch;
}
return v;
}
private static int i2sz(int i) {
return i * 3;
}
}

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,9 +27,12 @@ package org.graalvm.compiler.hotspot.lir.test;
import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine; import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine;
import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments; import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.LIRKind;
@ -121,6 +124,7 @@ public class BenchmarkCounterOverflowTest extends LIRTest {
Assert.assertNotEquals("Expected non-zero exit status", 0, proc.exitCode); Assert.assertNotEquals("Expected non-zero exit status", 0, proc.exitCode);
Iterator<String> it = proc.output.iterator(); Iterator<String> it = proc.output.iterator();
boolean foundProblematicFrame = false;
while (it.hasNext()) { while (it.hasNext()) {
String line = it.next(); String line = it.next();
if (line.contains("Problematic frame:")) { if (line.contains("Problematic frame:")) {
@ -130,11 +134,34 @@ public class BenchmarkCounterOverflowTest extends LIRTest {
} }
line = it.next(); line = it.next();
if (line.contains(BenchmarkCounterOverflowTest.class.getName() + ".test")) { if (line.contains(BenchmarkCounterOverflowTest.class.getName() + ".test")) {
return; foundProblematicFrame = true;
break;
} }
Assert.fail("Unexpected stack trace: " + line); Assert.fail("Unexpected stack trace: " + line);
} }
} }
Assert.fail(String.format("Could not find method in output:%n%s", proc)); // find and delete hserr file
while (it.hasNext()) {
String line = it.next();
if (line.contains("An error report file with more information is saved as:")) {
if (!it.hasNext()) {
// no more line
break;
}
line = it.next();
Pattern pattern = Pattern.compile("^# (.*hs_err_pid.*log)$");
Matcher matcher = pattern.matcher(line);
if (matcher.matches()) {
File hserrFile = new File(matcher.group(1));
if (hserrFile.exists()) {
if (VERBOSE) {
System.out.println("Deleting error report file:" + hserrFile.getAbsolutePath());
}
hserrFile.delete();
}
}
}
}
Assert.assertTrue(String.format("Could not find method in output:%n%s", proc), foundProblematicFrame);
} }
} }

View File

@ -63,6 +63,7 @@ import org.graalvm.compiler.code.DataSection.Data;
import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.core.gen.LIRGenerationProvider;
import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules; import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules;
import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext;
@ -109,7 +110,7 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
/** /**
* HotSpot SPARC specific backend. * HotSpot SPARC specific backend.
*/ */
public class SPARCHotSpotBackend extends HotSpotHostBackend { public class SPARCHotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider {
private static final SizeEstimateStatistics CONSTANT_ESTIMATED_STATS = new SizeEstimateStatistics("ESTIMATE"); private static final SizeEstimateStatistics CONSTANT_ESTIMATED_STATS = new SizeEstimateStatistics("ESTIMATE");
private static final SizeEstimateStatistics CONSTANT_ACTUAL_STATS = new SizeEstimateStatistics("ACTUAL"); private static final SizeEstimateStatistics CONSTANT_ACTUAL_STATS = new SizeEstimateStatistics("ACTUAL");
@ -134,15 +135,10 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend {
} }
} }
@Override private FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
return new SPARCFrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull); FrameMap frameMap = new SPARCFrameMap(getCodeCache(), registerConfigNonNull, this);
} return new SPARCFrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull);
@Override
public FrameMap newFrameMap(RegisterConfig registerConfig) {
return new SPARCFrameMap(getCodeCache(), registerConfig, this);
} }
@Override @Override
@ -151,8 +147,9 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend {
} }
@Override @Override
public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, Object stub) { public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, Object stub) {
return new HotSpotLIRGenerationResult(compilationId, lir, frameMapBuilder, makeCallingConvention(graph, (Stub) stub), stub, config.requiresReservedStackCheck(graph.getMethods())); return new HotSpotLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerConfig), makeCallingConvention(graph, (Stub) stub), stub,
config.requiresReservedStackCheck(graph.getMethods()));
} }
@Override @Override
@ -226,11 +223,6 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend {
} }
} }
@Override
protected Assembler createAssembler(FrameMap frameMap) {
return new SPARCMacroAssembler(getTarget());
}
@Override @Override
public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRes; HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRes;
@ -238,7 +230,7 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend {
assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
Stub stub = gen.getStub(); Stub stub = gen.getStub();
Assembler masm = createAssembler(frameMap); Assembler masm = new SPARCMacroAssembler(getTarget());
// On SPARC we always use stack frames. // On SPARC we always use stack frames.
HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null);
DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget());

View File

@ -24,20 +24,21 @@
package org.graalvm.compiler.hotspot.sparc; package org.graalvm.compiler.hotspot.sparc;
import static jdk.vm.ci.code.ValueUtil.asRegister;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPR; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPR;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.ANNUL; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.ANNUL;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_NOT_TAKEN;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_TAKEN; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_TAKEN;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.RCondition.Rc_nz;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.RCondition.Rc_z; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.RCondition.Rc_z;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
import static org.graalvm.compiler.lir.sparc.SPARCMove.loadFromConstantTable; import static org.graalvm.compiler.lir.sparc.SPARCMove.loadFromConstantTable;
import static jdk.vm.ci.code.ValueUtil.asRegister;
import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.sparc.SPARCAddress; import org.graalvm.compiler.asm.sparc.SPARCAddress;
import org.graalvm.compiler.asm.sparc.SPARCAssembler.CC;
import org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag;
import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister;
import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.CompressEncoding;
@ -53,6 +54,7 @@ import jdk.vm.ci.code.ValueUtil;
import jdk.vm.ci.hotspot.HotSpotConstant; import jdk.vm.ci.hotspot.HotSpotConstant;
import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.sparc.SPARC;
public class SPARCHotSpotMove { public class SPARCHotSpotMove {
@ -150,17 +152,33 @@ public class SPARCHotSpotMove {
if (encoding.hasBase()) { if (encoding.hasBase()) {
Register baseReg = asRegister(baseRegister); Register baseReg = asRegister(baseRegister);
if (!nonNull) { if (!nonNull) {
masm.cmp(inputRegister, baseReg); Label done = new Label();
masm.movcc(ConditionFlag.Equal, CC.Xcc, baseReg, resReg); if (inputRegister.equals(resReg)) {
masm.sub(resReg, baseReg, resReg); BPR.emit(masm, Rc_nz, ANNUL, PREDICT_TAKEN, inputRegister, done);
masm.sub(inputRegister, baseReg, resReg);
masm.bind(done);
if (encoding.getShift() != 0) {
masm.srlx(resReg, encoding.getShift(), resReg);
}
} else {
BPR.emit(masm, Rc_z, NOT_ANNUL, PREDICT_NOT_TAKEN, inputRegister, done);
masm.mov(SPARC.g0, resReg);
masm.sub(inputRegister, baseReg, resReg);
if (encoding.getShift() != 0) {
masm.srlx(resReg, encoding.getShift(), resReg);
}
masm.bind(done);
}
} else { } else {
masm.sub(inputRegister, baseReg, resReg); masm.sub(inputRegister, baseReg, resReg);
} if (encoding.getShift() != 0) {
if (encoding.getShift() != 0) { masm.srlx(resReg, encoding.getShift(), resReg);
masm.srlx(resReg, encoding.getShift(), resReg); }
} }
} else { } else {
masm.srlx(inputRegister, encoding.getShift(), resReg); if (encoding.getShift() != 0) {
masm.srlx(inputRegister, encoding.getShift(), resReg);
}
} }
} }
} }
@ -196,7 +214,7 @@ public class SPARCHotSpotMove {
public static void emitUncompressCode(SPARCMacroAssembler masm, Register inputRegister, Register resReg, Register baseReg, int shift, boolean nonNull) { public static void emitUncompressCode(SPARCMacroAssembler masm, Register inputRegister, Register resReg, Register baseReg, int shift, boolean nonNull) {
Register secondaryInput; Register secondaryInput;
if (shift != 0) { if (shift != 0) {
masm.sll(inputRegister, shift, resReg); masm.sllx(inputRegister, shift, resReg);
secondaryInput = resReg; secondaryInput = resReg;
} else { } else {
secondaryInput = inputRegister; secondaryInput = inputRegister;
@ -207,7 +225,7 @@ public class SPARCHotSpotMove {
masm.add(secondaryInput, baseReg, resReg); masm.add(secondaryInput, baseReg, resReg);
} else { } else {
Label done = new Label(); Label done = new Label();
BPR.emit(masm, Rc_z, ANNUL, PREDICT_TAKEN, secondaryInput, done); BPR.emit(masm, Rc_nz, ANNUL, PREDICT_TAKEN, secondaryInput, done);
masm.add(baseReg, secondaryInput, resReg); masm.add(baseReg, secondaryInput, resReg);
masm.bind(done); masm.bind(done);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -47,7 +47,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding;
import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.compiler.runtime.RuntimeProvider;
import org.graalvm.compiler.serviceprovider.GraalServices; import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.test.GraalTest; import org.graalvm.compiler.test.GraalTest;
import org.junit.Test; import org.junit.Test;
@ -257,7 +257,8 @@ public class CheckGraalIntrinsics extends GraalTest {
"java/lang/reflect/Array.newArray(Ljava/lang/Class;I)Ljava/lang/Object;", "java/lang/reflect/Array.newArray(Ljava/lang/Class;I)Ljava/lang/Object;",
// HotSpot MacroAssembler-based intrinsic // HotSpot MacroAssembler-based intrinsic
"sun/nio/cs/ISO_8859_1$Encoder.encodeISOArray([CI[BII)I", "sun/nio/cs/ISO_8859_1$Encoder.encodeISOArray([CI[BII)I",
// Stub based intrinsics but implementation seems complex in C2 // We have implemented implCompressMultiBlock0 on JDK9+. Does it worth
// backporting as corresponding HotSpot stubs are only generated on SPARC?
"sun/security/provider/DigestBase.implCompressMultiBlock([BII)I"); "sun/security/provider/DigestBase.implCompressMultiBlock([BII)I");
// See JDK-8207146. // See JDK-8207146.
@ -271,18 +272,12 @@ public class CheckGraalIntrinsics extends GraalTest {
"jdk/jfr/internal/JVM.getClassId(Ljava/lang/Class;)J"); "jdk/jfr/internal/JVM.getClassId(Ljava/lang/Class;)J");
add(toBeInvestigated, add(toBeInvestigated,
// Some logic and a stub call
"com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I",
// Stub and very little logic
"com/sun/crypto/provider/GHASH.processBlocks([BII[J[J)V",
// HotSpot MacroAssembler-based intrinsic // HotSpot MacroAssembler-based intrinsic
"java/lang/Math.fma(DDD)D", "java/lang/Math.fma(DDD)D",
// HotSpot MacroAssembler-based intrinsic // HotSpot MacroAssembler-based intrinsic
"java/lang/Math.fma(FFF)F", "java/lang/Math.fma(FFF)F",
// Just check if the argument is a compile time constant // Just check if the argument is a compile time constant
"java/lang/invoke/MethodHandleImpl.isCompileConstant(Ljava/lang/Object;)Z", "java/lang/invoke/MethodHandleImpl.isCompileConstant(Ljava/lang/Object;)Z",
// Some logic and a runtime call
"java/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I",
// Only used as a marker for vectorization? // Only used as a marker for vectorization?
"java/util/stream/Streams$RangeIntSpliterator.forEachRemaining(Ljava/util/function/IntConsumer;)V", "java/util/stream/Streams$RangeIntSpliterator.forEachRemaining(Ljava/util/function/IntConsumer;)V",
// Only implemented on non-AMD64 platforms (some logic and runtime call) // Only implemented on non-AMD64 platforms (some logic and runtime call)
@ -295,9 +290,7 @@ public class CheckGraalIntrinsics extends GraalTest {
// Control flow, deopts, and a cast // Control flow, deopts, and a cast
"jdk/internal/util/Preconditions.checkIndex(IILjava/util/function/BiFunction;)I", "jdk/internal/util/Preconditions.checkIndex(IILjava/util/function/BiFunction;)I",
// HotSpot MacroAssembler-based intrinsic // HotSpot MacroAssembler-based intrinsic
"sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray([CI[BII)I", "sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray([CI[BII)I");
// Runtime call and some complex compiler logic
"sun/security/provider/DigestBase.implCompressMultiBlock0([BII)I");
/* /*
* Per default, all these operations are mapped to some generic method for which we * Per default, all these operations are mapped to some generic method for which we
@ -344,27 +337,45 @@ public class CheckGraalIntrinsics extends GraalTest {
// Compact string support - HotSpot MacroAssembler-based intrinsic or complex C2 logic. // Compact string support - HotSpot MacroAssembler-based intrinsic or complex C2 logic.
add(toBeInvestigated, add(toBeInvestigated,
"java/lang/StringCoding.hasNegatives([BII)Z", "java/lang/StringCoding.hasNegatives([BII)Z",
"java/lang/StringCoding.implEncodeISOArray([BI[BII)I", "java/lang/StringCoding.implEncodeISOArray([BI[BII)I");
add(ignore,
// handled through an intrinsic for String.equals itself
"java/lang/StringLatin1.equals([B[B)Z",
// handled by an intrinsic for StringLatin1.indexOf([BI[BII)I
"java/lang/StringLatin1.indexOf([B[B)I", "java/lang/StringLatin1.indexOf([B[B)I",
"java/lang/StringUTF16.getChar([BI)C",
"java/lang/StringUTF16.getChars([BII[CI)V", // handled through an intrinsic for String.equals itself
"java/lang/StringUTF16.equals([B[B)Z",
// handled by an intrinsic for StringUTF16.indexOfUnsafe
"java/lang/StringUTF16.indexOf([BI[BII)I", "java/lang/StringUTF16.indexOf([BI[BII)I",
"java/lang/StringUTF16.indexOf([B[B)I", "java/lang/StringUTF16.indexOf([B[B)I",
// handled by an intrinsic for StringUTF16.indexOfCharUnsafe
"java/lang/StringUTF16.indexOfChar([BIII)I", "java/lang/StringUTF16.indexOfChar([BIII)I",
// handled by an intrinsic for StringUTF16.indexOfLatin1Unsafe
"java/lang/StringUTF16.indexOfLatin1([BI[BII)I", "java/lang/StringUTF16.indexOfLatin1([BI[BII)I",
"java/lang/StringUTF16.indexOfLatin1([B[B)I", "java/lang/StringUTF16.indexOfLatin1([B[B)I");
"java/lang/StringUTF16.putChar([BII)V",
"java/lang/StringUTF16.toBytes([CII)[B"); if (!config.useAESCTRIntrinsics) {
// These are handled through an intrinsic for String.equals itself add(ignore,
add(ignore, "com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I");
"java/lang/StringLatin1.equals([B[B)Z", }
"java/lang/StringUTF16.equals([B[B)Z"); if (!config.useGHASHIntrinsics()) {
add(ignore,
"com/sun/crypto/provider/GHASH.processBlocks([BII[J[J)V");
}
if (!(config.useSHA1Intrinsics() || config.useSHA256Intrinsics() || config.useSHA512Intrinsics())) {
add(ignore,
"sun/security/provider/DigestBase.implCompressMultiBlock0([BII)I");
}
} }
if (isJDK10OrHigher()) { if (isJDK10OrHigher()) {
add(toBeInvestigated, add(toBeInvestigated,
"java/lang/Math.multiplyHigh(JJ)J", "java/lang/Math.multiplyHigh(JJ)J");
"jdk/internal/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I");
} }
if (isJDK11OrHigher()) { if (isJDK11OrHigher()) {
@ -401,10 +412,16 @@ public class CheckGraalIntrinsics extends GraalTest {
// Can we implement these on non-AMD64 platforms? C2 seems to. // Can we implement these on non-AMD64 platforms? C2 seems to.
add(toBeInvestigated, add(toBeInvestigated,
"java/lang/String.compareTo(Ljava/lang/String;)I", "java/lang/String.compareTo(Ljava/lang/String;)I",
"java/lang/StringLatin1.indexOf([B[B)I",
"java/lang/StringLatin1.inflate([BI[BII)V", "java/lang/StringLatin1.inflate([BI[BII)V",
"java/lang/StringLatin1.inflate([BI[CII)V", "java/lang/StringLatin1.inflate([BI[CII)V",
"java/lang/StringUTF16.compress([BI[BII)I", "java/lang/StringUTF16.compress([BI[BII)I",
"java/lang/StringUTF16.compress([CI[BII)I", "java/lang/StringUTF16.compress([CI[BII)I",
"java/lang/StringUTF16.indexOf([BI[BII)I",
"java/lang/StringUTF16.indexOf([B[B)I",
"java/lang/StringUTF16.indexOfChar([BIII)I",
"java/lang/StringUTF16.indexOfLatin1([BI[BII)I",
"java/lang/StringUTF16.indexOfLatin1([B[B)I",
"jdk/internal/misc/Unsafe.compareAndExchangeByte(Ljava/lang/Object;JBB)B", "jdk/internal/misc/Unsafe.compareAndExchangeByte(Ljava/lang/Object;JBB)B",
"jdk/internal/misc/Unsafe.compareAndExchangeShort(Ljava/lang/Object;JSS)S", "jdk/internal/misc/Unsafe.compareAndExchangeShort(Ljava/lang/Object;JSS)S",
"jdk/internal/misc/Unsafe.compareAndSetByte(Ljava/lang/Object;JBB)Z", "jdk/internal/misc/Unsafe.compareAndSetByte(Ljava/lang/Object;JBB)Z",
@ -433,7 +450,9 @@ public class CheckGraalIntrinsics extends GraalTest {
"jdk/internal/misc/Unsafe.getAndSet" + oopName + "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;"); "jdk/internal/misc/Unsafe.getAndSet" + oopName + "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;");
} }
add(toBeInvestigated, add(toBeInvestigated,
"com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I",
"java/lang/Thread.onSpinWait()V", "java/lang/Thread.onSpinWait()V",
"java/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I",
"jdk/internal/misc/Unsafe.getCharUnaligned(Ljava/lang/Object;J)C", "jdk/internal/misc/Unsafe.getCharUnaligned(Ljava/lang/Object;J)C",
"jdk/internal/misc/Unsafe.getIntUnaligned(Ljava/lang/Object;J)I", "jdk/internal/misc/Unsafe.getIntUnaligned(Ljava/lang/Object;J)I",
"jdk/internal/misc/Unsafe.getLongUnaligned(Ljava/lang/Object;J)J", "jdk/internal/misc/Unsafe.getLongUnaligned(Ljava/lang/Object;J)J",
@ -443,6 +462,10 @@ public class CheckGraalIntrinsics extends GraalTest {
"jdk/internal/misc/Unsafe.putLongUnaligned(Ljava/lang/Object;JJ)V", "jdk/internal/misc/Unsafe.putLongUnaligned(Ljava/lang/Object;JJ)V",
"jdk/internal/misc/Unsafe.putShortUnaligned(Ljava/lang/Object;JS)V"); "jdk/internal/misc/Unsafe.putShortUnaligned(Ljava/lang/Object;JS)V");
} }
if (isJDK10OrHigher()) {
add(toBeInvestigated,
"jdk/internal/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I");
}
} }
/* /*
@ -535,23 +558,23 @@ public class CheckGraalIntrinsics extends GraalTest {
} }
private static boolean isJDK9OrHigher() { private static boolean isJDK9OrHigher() {
return GraalServices.JAVA_SPECIFICATION_VERSION >= 9; return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 9;
} }
private static boolean isJDK10OrHigher() { private static boolean isJDK10OrHigher() {
return GraalServices.JAVA_SPECIFICATION_VERSION >= 10; return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 10;
} }
private static boolean isJDK11OrHigher() { private static boolean isJDK11OrHigher() {
return GraalServices.JAVA_SPECIFICATION_VERSION >= 11; return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 11;
} }
private static boolean isJDK12OrHigher() { private static boolean isJDK12OrHigher() {
return GraalServices.JAVA_SPECIFICATION_VERSION >= 12; return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 12;
} }
private static boolean isJDK13OrHigher() { private static boolean isJDK13OrHigher() {
return GraalServices.JAVA_SPECIFICATION_VERSION >= 13; return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 13;
} }
public interface Refiner { public interface Refiner {

View File

@ -31,7 +31,7 @@ import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureA
import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries; import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries;
import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes; import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes;
import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS; import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS;
import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier; import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
import java.io.Closeable; import java.io.Closeable;
import java.io.File; import java.io.File;
@ -90,7 +90,7 @@ import org.graalvm.compiler.options.OptionDescriptors;
import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.options.OptionsParser; import org.graalvm.compiler.options.OptionsParser;
import org.graalvm.compiler.serviceprovider.GraalServices; import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
@ -110,7 +110,7 @@ public final class CompileTheWorld {
/** /**
* Magic token to denote that JDK classes are to be compiled. If * Magic token to denote that JDK classes are to be compiled. If
* {@link GraalServices#Java8OrEarlier}, then the classes in {@code rt.jar} are compiled. * {@link JavaVersionUtil#Java8OrEarlier}, then the classes in {@code rt.jar} are compiled.
* Otherwise the classes in the Java runtime image are compiled. * Otherwise the classes in the Java runtime image are compiled.
*/ */
public static final String SUN_BOOT_CLASS_PATH = "sun.boot.class.path"; public static final String SUN_BOOT_CLASS_PATH = "sun.boot.class.path";

View File

@ -0,0 +1,224 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.test;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin;
import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.junit.Assert;
import org.junit.Test;
public class EliminateRedundantInitializationPhaseTest extends GraalCompilerTest {
@Override
protected Plugins getDefaultGraphBuilderPlugins() {
Plugins plugins = super.getDefaultGraphBuilderPlugins();
plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin());
return plugins;
}
public static class X {
public static int x;
public static int y;
public static int z;
}
public static class Y extends X {
public static int a;
public static int b;
}
public static void assignFields() {
X.x = 1;
X.y = 2;
X.z = 3;
}
public static void assignFieldsConditionally(boolean choice) {
X.x = 1;
if (choice) {
X.y = 2;
} else {
X.z = 3;
}
}
public static void assignFieldsSubclassDominates() {
Y.a = 1;
X.x = 2;
X.y = 3;
X.z = 4;
}
public static void assignFieldsConditionallySubclassDominates(boolean choice) {
Y.a = 1;
if (choice) {
X.x = 2;
} else {
X.y = 3;
}
Y.z = 4;
}
public static void assignFieldsSubclassPostdominates() {
X.x = 1;
Y.a = 2;
}
public static void assignFieldsConditionallySubclassPostdominates(boolean choice) {
X.x = 1;
if (choice) {
X.y = 2;
} else {
X.z = 3;
}
Y.a = 4;
}
public static void assignFieldsConditionallyMixed(boolean choice) {
X.x = 1;
if (choice) {
Y.a = 2;
} else {
X.z = 3;
}
Y.b = 4;
}
public static void assignFieldsInLoop() {
X.x = 1;
for (int i = 0; i < 10; i++) {
X.y += X.z;
}
}
public static void assignFieldsInBranches(boolean choice) {
if (choice) {
X.x = 1;
} else {
X.y = 2;
}
X.z = 3;
}
public static void assignFieldsInBranchesMixed(boolean choice) {
if (choice) {
X.x = 1;
} else {
Y.a = 2;
}
X.z = 3;
}
static class SomeClass {
@BytecodeParserNeverInline
static void method() {
}
@BytecodeParserForceInline
static void inlinedMethod() {
}
}
public static void invokestatic() {
SomeClass.method();
}
public static void invokestaticInlined() {
SomeClass.inlinedMethod();
}
private void test(String name, int initNodesAfterParse, int initNodesAfterOpt) {
StructuredGraph graph = parseEager(name, AllowAssumptions.NO);
Assert.assertEquals(initNodesAfterParse, graph.getNodes().filter(InitializeKlassNode.class).count());
HighTierContext highTierContext = getDefaultHighTierContext();
new EliminateRedundantInitializationPhase().apply(graph, highTierContext);
Assert.assertEquals(initNodesAfterOpt, graph.getNodes().filter(InitializeKlassNode.class).count());
}
@Test
public void test1() {
test("assignFields", 3, 1);
}
@Test
public void test2() {
test("assignFieldsConditionally", 3, 1);
}
@Test
public void test3() {
test("assignFieldsSubclassDominates", 4, 1);
}
@Test
public void test4() {
test("assignFieldsConditionallySubclassDominates", 4, 1);
}
@Test
public void test5() {
test("assignFieldsSubclassPostdominates", 2, 2);
}
@Test
public void test6() {
test("assignFieldsConditionallySubclassPostdominates", 4, 2);
}
@Test
public void test7() {
test("assignFieldsConditionallyMixed", 4, 3);
}
@Test
public void test8() {
test("assignFieldsInLoop", 4, 1);
}
@Test
public void test9() {
test("assignFieldsInBranches", 3, 2);
}
@Test
public void test10() {
test("assignFieldsInBranchesMixed", 3, 2);
}
@Test
public void test11() {
test("invokestatic", 1, 0);
}
@Test
public void test12() {
test("invokestaticInlined", 1, 1);
}
}

View File

@ -53,6 +53,11 @@ public class GraalOSRTest extends GraalOSRTestBase {
testOSR(getInitialOptions(), "testNonReduceLoop"); testOSR(getInitialOptions(), "testNonReduceLoop");
} }
@Test
public void testOSR04() {
testOSR(getInitialOptions(), "testDeoptAfterCountedLoop");
}
static int limit = 10000; static int limit = 10000;
public static int sideEffect; public static int sideEffect;
@ -100,4 +105,14 @@ public class GraalOSRTest extends GraalOSRTestBase {
GraalDirectives.controlFlowAnchor(); GraalDirectives.controlFlowAnchor();
return ret; return ret;
} }
public static ReturnValue testDeoptAfterCountedLoop() {
long ret = 0;
for (int i = 0; GraalDirectives.injectBranchProbability(1, i < limit * limit); i++) {
GraalDirectives.blackhole(i);
ret = GraalDirectives.opaque(i);
}
GraalDirectives.controlFlowAnchor();
return ret + 1 == limit * limit ? ReturnValue.SUCCESS : ReturnValue.FAILURE;
}
} }

View File

@ -24,6 +24,7 @@
package org.graalvm.compiler.hotspot.test; package org.graalvm.compiler.hotspot.test;
import static org.graalvm.compiler.debug.DebugOptions.DumpOnError;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
@ -52,6 +53,7 @@ import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode;
import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.options.OptionValues;
import org.junit.Test; import org.junit.Test;
import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.BytecodeFrame;
@ -139,6 +141,14 @@ public class JVMCIInfopointErrorTest extends GraalCompilerTest {
test(getDebugContext(), spec); test(getDebugContext(), spec);
} }
/**
* Avoids dumping during tests which are expected to fail.
*/
private void testNoDump(TestSpec spec) {
OptionValues options = new OptionValues(getInitialOptions(), DumpOnError, false);
test(getDebugContext(options, null, null), spec);
}
private void test(DebugContext debug, TestSpec spec) { private void test(DebugContext debug, TestSpec spec) {
ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); ResolvedJavaMethod method = getResolvedJavaMethod("testMethod");
@ -154,7 +164,7 @@ public class JVMCIInfopointErrorTest extends GraalCompilerTest {
@Test(expected = Error.class) @Test(expected = Error.class)
public void testInvalidShortOop() { public void testInvalidShortOop() {
test((tool, state, safepoint) -> { testNoDump((tool, state, safepoint) -> {
PlatformKind kind = tool.target().arch.getPlatformKind(JavaKind.Short); PlatformKind kind = tool.target().arch.getPlatformKind(JavaKind.Short);
LIRKind lirKind = LIRKind.reference(kind); LIRKind lirKind = LIRKind.reference(kind);
@ -167,7 +177,7 @@ public class JVMCIInfopointErrorTest extends GraalCompilerTest {
@Test(expected = Error.class) @Test(expected = Error.class)
public void testInvalidShortDerivedOop() { public void testInvalidShortDerivedOop() {
test((tool, state, safepoint) -> { testNoDump((tool, state, safepoint) -> {
Variable baseOop = tool.newVariable(LIRKind.fromJavaKind(tool.target().arch, JavaKind.Object)); Variable baseOop = tool.newVariable(LIRKind.fromJavaKind(tool.target().arch, JavaKind.Object));
tool.append(new ValueDef(baseOop)); tool.append(new ValueDef(baseOop));

View File

@ -37,6 +37,7 @@ import java.io.PrintStream;
import java.util.List; import java.util.List;
import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.debug.DebugOptions.PrintGraphTarget;
import org.graalvm.compiler.test.SubprocessUtil; import org.graalvm.compiler.test.SubprocessUtil;
import org.graalvm.compiler.test.SubprocessUtil.Subprocess; import org.graalvm.compiler.test.SubprocessUtil.Subprocess;
import org.junit.Assert; import org.junit.Assert;
@ -54,12 +55,12 @@ public class OptionsInFileTest extends GraalCompilerTest {
try { try {
Assert.assertFalse(methodFilterValue.equals(MethodFilter.getDefaultValue())); Assert.assertFalse(methodFilterValue.equals(MethodFilter.getDefaultValue()));
Assert.assertFalse(debugFilterValue.equals(Dump.getDefaultValue())); Assert.assertFalse(debugFilterValue.equals(Dump.getDefaultValue()));
Assert.assertTrue(PrintGraph.getDefaultValue()); Assert.assertEquals(PrintGraphTarget.File, PrintGraph.getDefaultValue());
try (PrintStream out = new PrintStream(new FileOutputStream(optionsFile))) { try (PrintStream out = new PrintStream(new FileOutputStream(optionsFile))) {
out.println(MethodFilter.getName() + "=" + methodFilterValue); out.println(MethodFilter.getName() + "=" + methodFilterValue);
out.println(Dump.getName() + "=" + debugFilterValue); out.println(Dump.getName() + "=" + debugFilterValue);
out.println(PrintGraph.getName() + " = false"); out.println(PrintGraph.getName() + " = Network");
} }
List<String> vmArgs = withoutDebuggerArguments(getVMCommandLine()); List<String> vmArgs = withoutDebuggerArguments(getVMCommandLine());
@ -70,7 +71,7 @@ public class OptionsInFileTest extends GraalCompilerTest {
String[] expected = { String[] expected = {
"graal.MethodFilter := \"a very unlikely method name\"", "graal.MethodFilter := \"a very unlikely method name\"",
"graal.Dump := \"a very unlikely debug scope\"", "graal.Dump := \"a very unlikely debug scope\"",
"graal.PrintGraph := false"}; "graal.PrintGraph := Network"};
for (String line : proc.output) { for (String line : proc.output) {
for (int i = 0; i < expected.length; i++) { for (int i = 0; i < expected.length; i++) {
if (expected[i] != null && line.contains(expected[i])) { if (expected[i] != null && line.contains(expected[i])) {

View File

@ -73,6 +73,10 @@ public class ReservedStackAccessTest extends HotSpotGraalCompilerTest {
vmArgs.add("-XX:+UseJVMCICompiler"); vmArgs.add("-XX:+UseJVMCICompiler");
vmArgs.add("-Dgraal.Inline=false"); vmArgs.add("-Dgraal.Inline=false");
vmArgs.add("-XX:CompileCommand=exclude,java/util/concurrent/locks/AbstractOwnableSynchronizer.setExclusiveOwnerThread"); vmArgs.add("-XX:CompileCommand=exclude,java/util/concurrent/locks/AbstractOwnableSynchronizer.setExclusiveOwnerThread");
// Avoid SOE in HotSpotJVMCIRuntime.adjustCompilationLevel
vmArgs.add("-Dgraal.CompileGraalWithC1Only=false");
Subprocess proc = SubprocessUtil.java(vmArgs, ReservedStackAccessTest.class.getName()); Subprocess proc = SubprocessUtil.java(vmArgs, ReservedStackAccessTest.class.getName());
boolean passed = false; boolean passed = false;
for (String line : proc.output) { for (String line : proc.output) {
@ -81,9 +85,7 @@ public class ReservedStackAccessTest extends HotSpotGraalCompilerTest {
} }
} }
if (!passed) { if (!passed) {
for (String line : proc.output) { System.err.println(proc);
System.err.println("" + line);
}
} }
assertTrue(passed); assertTrue(passed);
} }

View File

@ -32,10 +32,10 @@ import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase;
import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier;
import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; import org.graalvm.compiler.hotspot.gc.g1.G1PreWriteBarrier;
import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier; import org.graalvm.compiler.hotspot.gc.g1.G1ReferentFieldReadBarrier;
import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier;
import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;

View File

@ -32,12 +32,12 @@ import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugContext.Scope; import org.graalvm.compiler.debug.DebugContext.Scope;
import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.debug.DebugDumpScope;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier; import org.graalvm.compiler.hotspot.gc.g1.G1ArrayRangePostWriteBarrier;
import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier; import org.graalvm.compiler.hotspot.gc.g1.G1ArrayRangePreWriteBarrier;
import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier;
import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; import org.graalvm.compiler.hotspot.gc.g1.G1PreWriteBarrier;
import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier; import org.graalvm.compiler.hotspot.gc.shared.SerialArrayRangeWriteBarrier;
import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier;
import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase; import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase;
import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractBeginNode;

View File

@ -368,8 +368,14 @@ public class CompilationTask {
installedCode = null; installedCode = null;
Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult}; Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult};
try (DebugContext.Scope s = debug.scope("CodeInstall", context)) { try (DebugContext.Scope s = debug.scope("CodeInstall", context)) {
installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug, getRequest().getMethod(), getRequest(), compResult, HotSpotCompilationRequest request = getRequest();
getRequest().getMethod().getSpeculationLog(), null, installAsDefault, context); installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug,
request.getMethod(),
request,
compResult,
null,
installAsDefault,
context);
} catch (Throwable e) { } catch (Throwable e) {
throw debug.handle(e); throw debug.handle(e);
} }

View File

@ -92,6 +92,7 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
public final boolean useBiasedLocking = getFlag("UseBiasedLocking", Boolean.class); public final boolean useBiasedLocking = getFlag("UseBiasedLocking", Boolean.class);
public final boolean usePopCountInstruction = getFlag("UsePopCountInstruction", Boolean.class); public final boolean usePopCountInstruction = getFlag("UsePopCountInstruction", Boolean.class);
public final boolean useAESIntrinsics = getFlag("UseAESIntrinsics", Boolean.class); public final boolean useAESIntrinsics = getFlag("UseAESIntrinsics", Boolean.class);
public final boolean useAESCTRIntrinsics = getFlag("UseAESCTRIntrinsics", Boolean.class, false);
public final boolean useCRC32Intrinsics = getFlag("UseCRC32Intrinsics", Boolean.class); public final boolean useCRC32Intrinsics = getFlag("UseCRC32Intrinsics", Boolean.class);
public final boolean useCRC32CIntrinsics = versioned.useCRC32CIntrinsics; public final boolean useCRC32CIntrinsics = versioned.useCRC32CIntrinsics;
public final boolean threadLocalHandshakes = getFlag("ThreadLocalHandshakes", Boolean.class, false); public final boolean threadLocalHandshakes = getFlag("ThreadLocalHandshakes", Boolean.class, false);
@ -100,10 +101,12 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
private final boolean useSHA1Intrinsics = getFlag("UseSHA1Intrinsics", Boolean.class); private final boolean useSHA1Intrinsics = getFlag("UseSHA1Intrinsics", Boolean.class);
private final boolean useSHA256Intrinsics = getFlag("UseSHA256Intrinsics", Boolean.class); private final boolean useSHA256Intrinsics = getFlag("UseSHA256Intrinsics", Boolean.class);
private final boolean useSHA512Intrinsics = getFlag("UseSHA512Intrinsics", Boolean.class); private final boolean useSHA512Intrinsics = getFlag("UseSHA512Intrinsics", Boolean.class);
private final boolean useGHASHIntrinsics = getFlag("UseGHASHIntrinsics", Boolean.class, false);
private final boolean useMontgomeryMultiplyIntrinsic = getFlag("UseMontgomeryMultiplyIntrinsic", Boolean.class, false); private final boolean useMontgomeryMultiplyIntrinsic = getFlag("UseMontgomeryMultiplyIntrinsic", Boolean.class, false);
private final boolean useMontgomerySquareIntrinsic = getFlag("UseMontgomerySquareIntrinsic", Boolean.class, false); private final boolean useMontgomerySquareIntrinsic = getFlag("UseMontgomerySquareIntrinsic", Boolean.class, false);
private final boolean useMulAddIntrinsic = getFlag("UseMulAddIntrinsic", Boolean.class, false); private final boolean useMulAddIntrinsic = getFlag("UseMulAddIntrinsic", Boolean.class, false);
private final boolean useSquareToLenIntrinsic = getFlag("UseSquareToLenIntrinsic", Boolean.class, false); private final boolean useSquareToLenIntrinsic = getFlag("UseSquareToLenIntrinsic", Boolean.class, false);
public final boolean useVectorizedMismatchIntrinsic = getFlag("UseVectorizedMismatchIntrinsic", Boolean.class, false);
/* /*
* These are methods because in some JDKs the flags are visible but the stubs themselves haven't * These are methods because in some JDKs the flags are visible but the stubs themselves haven't
@ -114,15 +117,19 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
} }
public boolean useSHA1Intrinsics() { public boolean useSHA1Intrinsics() {
return useSHA1Intrinsics && sha1ImplCompress != 0; return useSHA1Intrinsics && sha1ImplCompress != 0 && sha1ImplCompressMultiBlock != 0;
} }
public boolean useSHA256Intrinsics() { public boolean useSHA256Intrinsics() {
return useSHA256Intrinsics && sha256ImplCompress != 0; return useSHA256Intrinsics && sha256ImplCompress != 0 && sha256ImplCompressMultiBlock != 0;
} }
public boolean useSHA512Intrinsics() { public boolean useSHA512Intrinsics() {
return useSHA512Intrinsics && sha512ImplCompress != 0; return useSHA512Intrinsics && sha512ImplCompress != 0 && sha512ImplCompressMultiBlock != 0;
}
public boolean useGHASHIntrinsics() {
return useGHASHIntrinsics && ghashProcessBlocks != 0;
} }
public boolean useMontgomeryMultiplyIntrinsic() { public boolean useMontgomeryMultiplyIntrinsic() {
@ -309,7 +316,17 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
public final int jvmAccWrittenFlags = getConstant("JVM_ACC_WRITTEN_FLAGS", Integer.class); public final int jvmAccWrittenFlags = getConstant("JVM_ACC_WRITTEN_FLAGS", Integer.class);
public final int jvmAccSynthetic = getConstant("JVM_ACC_SYNTHETIC", Integer.class); public final int jvmAccSynthetic = getConstant("JVM_ACC_SYNTHETIC", Integer.class);
public final int jvmciCompileStateCanPostOnExceptionsOffset = getFieldOffset("JVMCIEnv::_jvmti_can_post_on_exceptions", Integer.class, "jbyte", Integer.MIN_VALUE); public final int jvmciCompileStateCanPostOnExceptionsOffset = getJvmciCompileStateCanPostOnExceptionsOffset();
// Integer.MIN_VALUE if not available
private int getJvmciCompileStateCanPostOnExceptionsOffset() {
int offset = getFieldOffset("JVMCICompileState::_jvmti_can_post_on_exceptions", Integer.class, "jbyte", Integer.MIN_VALUE);
if (offset == Integer.MIN_VALUE) {
// JDK 12
offset = getFieldOffset("JVMCIEnv::_jvmti_can_post_on_exceptions", Integer.class, "jbyte", Integer.MIN_VALUE);
}
return offset;
}
public final int threadTlabOffset = getFieldOffset("Thread::_tlab", Integer.class, "ThreadLocalAllocBuffer"); public final int threadTlabOffset = getFieldOffset("Thread::_tlab", Integer.class, "ThreadLocalAllocBuffer");
public final int javaThreadAnchorOffset = getFieldOffset("JavaThread::_anchor", Integer.class, "JavaFrameAnchor"); public final int javaThreadAnchorOffset = getFieldOffset("JavaThread::_anchor", Integer.class, "JavaFrameAnchor");
@ -372,12 +389,29 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
public final int pendingExceptionOffset = getFieldOffset("ThreadShadow::_pending_exception", Integer.class, "oop"); public final int pendingExceptionOffset = getFieldOffset("ThreadShadow::_pending_exception", Integer.class, "oop");
public final int pendingDeoptimizationOffset = getFieldOffset("JavaThread::_pending_deoptimization", Integer.class, "int"); public final int pendingDeoptimizationOffset = getFieldOffset("JavaThread::_pending_deoptimization", Integer.class, "int");
public final int pendingFailedSpeculationOffset = getFieldOffset("JavaThread::_pending_failed_speculation", Integer.class, "long");
public final int pendingTransferToInterpreterOffset = getFieldOffset("JavaThread::_pending_transfer_to_interpreter", Integer.class, "bool"); public final int pendingTransferToInterpreterOffset = getFieldOffset("JavaThread::_pending_transfer_to_interpreter", Integer.class, "bool");
private final int javaFrameAnchorLastJavaSpOffset = getFieldOffset("JavaFrameAnchor::_last_Java_sp", Integer.class, "intptr_t*"); private final int javaFrameAnchorLastJavaSpOffset = getFieldOffset("JavaFrameAnchor::_last_Java_sp", Integer.class, "intptr_t*");
private final int javaFrameAnchorLastJavaPcOffset = getFieldOffset("JavaFrameAnchor::_last_Java_pc", Integer.class, "address"); private final int javaFrameAnchorLastJavaPcOffset = getFieldOffset("JavaFrameAnchor::_last_Java_pc", Integer.class, "address");
public final int pendingFailedSpeculationOffset;
{
String name = "JavaThread::_pending_failed_speculation";
int offset = -1;
try {
offset = getFieldOffset(name, Integer.class, "jlong");
} catch (JVMCIError e) {
try {
offset = getFieldOffset(name, Integer.class, "long");
} catch (JVMCIError e2) {
}
}
if (offset == -1) {
throw new JVMCIError("cannot get offset of field " + name + " with type long or jlong");
}
pendingFailedSpeculationOffset = offset;
}
public int threadLastJavaSpOffset() { public int threadLastJavaSpOffset() {
return javaThreadAnchorOffset + javaFrameAnchorLastJavaSpOffset; return javaThreadAnchorOffset + javaFrameAnchorLastJavaSpOffset;
} }
@ -602,11 +636,11 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
public final long crcTableAddress = getFieldValue("StubRoutines::_crc_table_adr", Long.class, "address"); public final long crcTableAddress = getFieldValue("StubRoutines::_crc_table_adr", Long.class, "address");
public final long sha1ImplCompress = getFieldValue("StubRoutines::_sha1_implCompress", Long.class, "address", 0L); public final long sha1ImplCompress = getFieldValue("StubRoutines::_sha1_implCompress", Long.class, "address", 0L);
public final long sha1ImplCompressMB = getFieldValue("StubRoutines::_sha1_implCompressMB", Long.class, "address", 0L); public final long sha1ImplCompressMultiBlock = getFieldValue("StubRoutines::_sha1_implCompressMB", Long.class, "address", 0L);
public final long sha256ImplCompress = getFieldValue("StubRoutines::_sha256_implCompress", Long.class, "address", 0L); public final long sha256ImplCompress = getFieldValue("StubRoutines::_sha256_implCompress", Long.class, "address", 0L);
public final long sha256ImplCompressMB = getFieldValue("StubRoutines::_sha256_implCompressMB", Long.class, "address", 0L); public final long sha256ImplCompressMultiBlock = getFieldValue("StubRoutines::_sha256_implCompressMB", Long.class, "address", 0L);
public final long sha512ImplCompress = getFieldValue("StubRoutines::_sha512_implCompress", Long.class, "address", 0L); public final long sha512ImplCompress = getFieldValue("StubRoutines::_sha512_implCompress", Long.class, "address", 0L);
public final long sha512ImplCompressMB = getFieldValue("StubRoutines::_sha512_implCompressMB", Long.class, "address", 0L); public final long sha512ImplCompressMultiBlock = getFieldValue("StubRoutines::_sha512_implCompressMB", Long.class, "address", 0L);
public final long multiplyToLen = getFieldValue("StubRoutines::_multiplyToLen", Long.class, "address", longRequiredOnAMD64); public final long multiplyToLen = getFieldValue("StubRoutines::_multiplyToLen", Long.class, "address", longRequiredOnAMD64);
public final long counterModeAESCrypt = getFieldValue("StubRoutines::_counterMode_AESCrypt", Long.class, "address", 0L); public final long counterModeAESCrypt = getFieldValue("StubRoutines::_counterMode_AESCrypt", Long.class, "address", 0L);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -46,6 +46,7 @@ import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantStubCall;
import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions; import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions;
import org.graalvm.compiler.hotspot.replacements.BigIntegerSubstitutions; import org.graalvm.compiler.hotspot.replacements.BigIntegerSubstitutions;
import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions; import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions;
import org.graalvm.compiler.hotspot.replacements.DigestBaseSubstitutions;
import org.graalvm.compiler.hotspot.replacements.SHA2Substitutions; import org.graalvm.compiler.hotspot.replacements.SHA2Substitutions;
import org.graalvm.compiler.hotspot.replacements.SHA5Substitutions; import org.graalvm.compiler.hotspot.replacements.SHA5Substitutions;
import org.graalvm.compiler.hotspot.replacements.SHASubstitutions; import org.graalvm.compiler.hotspot.replacements.SHASubstitutions;
@ -71,6 +72,7 @@ import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.tiers.SuitesProvider; import org.graalvm.compiler.phases.tiers.SuitesProvider;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.Word;
import jdk.internal.vm.compiler.word.Pointer; import jdk.internal.vm.compiler.word.Pointer;
@ -95,7 +97,7 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen
public static class Options { public static class Options {
// @formatter:off // @formatter:off
@Option(help = "Use Graal arithmetic stubs instead of HotSpot stubs where possible") @Option(help = "Use Graal arithmetic stubs instead of HotSpot stubs where possible")
public static final OptionKey<Boolean> GraalArithmeticStubs = new OptionKey<>(false); // GR-8276 public static final OptionKey<Boolean> GraalArithmeticStubs = new OptionKey<>(JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 9);
@Option(help = "Enables instruction profiling on assembler level. Valid values are a comma separated list of supported instructions." + @Option(help = "Enables instruction profiling on assembler level. Valid values are a comma separated list of supported instructions." +
" Compare with subclasses of Assembler.InstructionCounter.", type = OptionType.Debug) " Compare with subclasses of Assembler.InstructionCounter.", type = OptionType.Debug)
public static final OptionKey<String> ASMInstructionProfiling = new OptionKey<>(null); public static final OptionKey<String> ASMInstructionProfiling = new OptionKey<>(null);
@ -261,6 +263,36 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen
@NodeIntrinsic(ForeignCallNode.class) @NodeIntrinsic(ForeignCallNode.class)
private static native void sha5ImplCompressStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state); private static native void sha5ImplCompressStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state);
/**
* @see DigestBaseSubstitutions#implCompressMultiBlock0
*/
public static final ForeignCallDescriptor SHA_IMPL_COMPRESS_MB = new ForeignCallDescriptor("shaImplCompressMB", int.class, Word.class, Object.class, int.class, int.class);
public static int shaImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) {
return shaImplCompressMBStub(HotSpotBackend.SHA_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit);
}
@NodeIntrinsic(ForeignCallNode.class)
private static native int shaImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit);
public static final ForeignCallDescriptor SHA2_IMPL_COMPRESS_MB = new ForeignCallDescriptor("sha2ImplCompressMB", int.class, Word.class, Object.class, int.class, int.class);
public static int sha2ImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) {
return sha2ImplCompressMBStub(HotSpotBackend.SHA2_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit);
}
@NodeIntrinsic(ForeignCallNode.class)
private static native int sha2ImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit);
public static final ForeignCallDescriptor SHA5_IMPL_COMPRESS_MB = new ForeignCallDescriptor("sha5ImplCompressMB", int.class, Word.class, Object.class, int.class, int.class);
public static int sha5ImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) {
return sha5ImplCompressMBStub(HotSpotBackend.SHA5_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit);
}
@NodeIntrinsic(ForeignCallNode.class)
private static native int sha5ImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit);
public static void unsafeArraycopy(Word srcAddr, Word dstAddr, Word size) { public static void unsafeArraycopy(Word srcAddr, Word dstAddr, Word size) {
unsafeArraycopyStub(UNSAFE_ARRAYCOPY, srcAddr, dstAddr, size); unsafeArraycopyStub(UNSAFE_ARRAYCOPY, srcAddr, dstAddr, size);
} }
@ -268,6 +300,37 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen
@NodeIntrinsic(ForeignCallNode.class) @NodeIntrinsic(ForeignCallNode.class)
private static native void unsafeArraycopyStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word srcAddr, Word dstAddr, Word size); private static native void unsafeArraycopyStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word srcAddr, Word dstAddr, Word size);
/**
* Descriptor for {@code StubRoutines::_ghash_processBlocks}.
*/
public static final ForeignCallDescriptor GHASH_PROCESS_BLOCKS = new ForeignCallDescriptor("ghashProcessBlocks", void.class, Word.class, Word.class, Word.class, int.class);
/**
* Descriptor for {@code StubRoutines::_counterMode_AESCrypt}.
*/
public static final ForeignCallDescriptor COUNTERMODE_IMPL_CRYPT = new ForeignCallDescriptor("counterModeAESCrypt", int.class, Word.class, Word.class, Word.class, Word.class, int.class,
Word.class, Word.class);
public static int counterModeAESCrypt(Word srcAddr, Word dstAddr, Word kPtr, Word cntPtr, int len, Word encCntPtr, Word used) {
return counterModeAESCrypt(COUNTERMODE_IMPL_CRYPT, srcAddr, dstAddr, kPtr, cntPtr, len, encCntPtr, used);
}
@NodeIntrinsic(ForeignCallNode.class)
private static native int counterModeAESCrypt(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word srcAddr, Word dstAddr, Word kPtr, Word cntPtr, int len, Word encCntPtr,
Word used);
/**
* Descriptor for {@code StubRoutines::_vectorizedMismatch}.
*/
public static final ForeignCallDescriptor VECTORIZED_MISMATCHED = new ForeignCallDescriptor("vectorizedMismatch", int.class, Word.class, Word.class, int.class, int.class);
public static int vectorizedMismatch(Word aAddr, Word bAddr, int length, int log2ArrayIndexScale) {
return vectorizedMismatchStub(VECTORIZED_MISMATCHED, aAddr, bAddr, length, log2ArrayIndexScale);
}
@NodeIntrinsic(ForeignCallNode.class)
private static native int vectorizedMismatchStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word aAddr, Word bAddr, int length, int log2ArrayIndexScale);
/** /**
* @see VMErrorNode * @see VMErrorNode
*/ */
@ -388,6 +451,13 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen
return translateToCallerRegisters(destroyedRegisters); return translateToCallerRegisters(destroyedRegisters);
} }
/**
* Translates a set of registers from the callee's perspective to the caller's perspective. This
* is needed for architectures where input/output registers are renamed during a call (e.g.
* register windows on SPARC). Registers which are not visible by the caller are removed.
*/
protected abstract EconomicSet<Register> translateToCallerRegisters(EconomicSet<Register> calleeRegisters);
/** /**
* Updates a given stub with respect to the registers it destroys. * Updates a given stub with respect to the registers it destroys.
* <p> * <p>

View File

@ -88,7 +88,7 @@ public class HotSpotCompiledCodeBuilder {
ResolvedJavaMethod[] methods = compResult.getMethods(); ResolvedJavaMethod[] methods = compResult.getMethods();
List<CodeAnnotation> annotations = compResult.getAnnotations(); List<CodeAnnotation> annotations = compResult.getCodeAnnotations();
Comment[] comments = new Comment[annotations.size()]; Comment[] comments = new Comment[annotations.size()];
if (!annotations.isEmpty()) { if (!annotations.isEmpty()) {
for (int i = 0; i < comments.length; i++) { for (int i = 0; i < comments.length; i++) {
@ -129,16 +129,16 @@ public class HotSpotCompiledCodeBuilder {
boolean hasUnsafeAccess = compResult.hasUnsafeAccess(); boolean hasUnsafeAccess = compResult.hasUnsafeAccess();
int id; int id;
long jvmciEnv; long jvmciCompileState;
if (compRequest != null) { if (compRequest != null) {
id = compRequest.getId(); id = compRequest.getId();
jvmciEnv = compRequest.getJvmciEnv(); jvmciCompileState = compRequest.getJvmciEnv();
} else { } else {
id = hsMethod.allocateCompileId(entryBCI); id = hsMethod.allocateCompileId(entryBCI);
jvmciEnv = 0L; jvmciCompileState = 0L;
} }
return new HotSpotCompiledNmethod(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC, return new HotSpotCompiledNmethod(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC,
totalFrameSize, customStackArea, hsMethod, entryBCI, id, jvmciEnv, hasUnsafeAccess); totalFrameSize, customStackArea, hsMethod, entryBCI, id, jvmciCompileState, hasUnsafeAccess);
} else { } else {
return new HotSpotCompiledCode(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC, return new HotSpotCompiledCode(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC,
totalFrameSize, customStackArea); totalFrameSize, customStackArea);

Some files were not shown because too many files have changed in this diff Show More