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.graph.test \
org.graalvm.compiler.hotspot.amd64.test \
org.graalvm.compiler.hotspot.jdk9.test \
org.graalvm.compiler.hotspot.lir.test \
org.graalvm.compiler.hotspot.sparc.test \
org.graalvm.compiler.hotspot.test \

View File

@ -92,6 +92,7 @@ ifeq ($(INCLUDE_GRAAL), true)
$(SRC_DIR)/org.graalvm.compiler.debug.test/src \
$(SRC_DIR)/org.graalvm.compiler.graph.test/src \
$(SRC_DIR)/org.graalvm.compiler.hotspot.amd64.test/src \
$(SRC_DIR)/org.graalvm.compiler.hotspot.jdk9.test/src \
$(SRC_DIR)/org.graalvm.compiler.hotspot.lir.test/src \
$(SRC_DIR)/org.graalvm.compiler.hotspot.sparc.test/src \
$(SRC_DIR)/org.graalvm.compiler.hotspot.test/src \

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.
*
* This code is free software; you can redistribute it and/or modify it
@ -29,6 +29,10 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Stream;
final class Linker {
@ -46,9 +50,12 @@ final class Linker {
return libraryFileName;
}
private static Stream<String> getLines(InputStream stream) {
return new BufferedReader(new InputStreamReader(stream)).lines();
}
private static String getString(InputStream stream) {
BufferedReader br = new BufferedReader(new InputStreamReader(stream));
Stream<String> lines = br.lines();
Stream<String> lines = getLines(stream);
StringBuilder sb = new StringBuilder();
lines.iterator().forEachRemaining(e -> sb.append(e));
return sb.toString();
@ -150,9 +157,18 @@ final class Linker {
}
/**
* Search for Visual Studio link.exe Search Order is: VS2013, VS2015, VS2012.
* Search for Visual Studio link.exe Search Order is: VS2017+, VS2013, VS2015, VS2012.
*/
private static String getWindowsLinkPath() {
private static String getWindowsLinkPath() throws Exception {
try {
Path vc141NewerLinker = getVC141AndNewerLinker();
if (vc141NewerLinker != null) {
return vc141NewerLinker.toString();
}
} catch (Exception e) {
e.printStackTrace();
}
String link = "\\VC\\bin\\amd64\\link.exe";
/**
@ -183,10 +199,46 @@ final class Linker {
return null;
}
private static Path getVC141AndNewerLinker() throws Exception {
String programFilesX86 = System.getenv("ProgramFiles(x86)");
if (programFilesX86 == null) {
throw new InternalError("Could not read the ProgramFiles(x86) environment variable");
}
Path vswhere = Paths.get(programFilesX86 + "\\Microsoft Visual Studio\\Installer\\vswhere.exe");
if (!Files.exists(vswhere)) {
return null;
}
ProcessBuilder processBuilder = new ProcessBuilder(vswhere.toString(), "-requires",
"Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "-property", "installationPath", "-latest");
processBuilder.redirectOutput(ProcessBuilder.Redirect.PIPE);
processBuilder.redirectError(ProcessBuilder.Redirect.PIPE);
Process process = processBuilder.start();
final int exitCode = process.waitFor();
if (exitCode != 0) {
String errorMessage = getString(process.getErrorStream());
if (errorMessage.isEmpty()) {
errorMessage = getString(process.getInputStream());
}
throw new InternalError(errorMessage);
}
String installationPath = getLines(process.getInputStream()).findFirst().orElseThrow(() -> new InternalError("Unexpected empty output from vswhere"));
Path vcToolsVersionFilePath = Paths.get(installationPath, "VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt");
List<String> vcToolsVersionFileLines = Files.readAllLines(vcToolsVersionFilePath);
if (vcToolsVersionFileLines.isEmpty()) {
throw new InternalError(vcToolsVersionFilePath.toString() + " is empty");
}
String vcToolsVersion = vcToolsVersionFileLines.get(0);
Path linkPath = Paths.get(installationPath, "VC\\Tools\\MSVC", vcToolsVersion, "bin\\Hostx64\\x64\\link.exe");
if (!Files.exists(linkPath)) {
throw new InternalError("Linker at path " + linkPath.toString() + " does not exist");
}
return linkPath;
}
// @formatter:off (workaround for Eclipse formatting bug)
/**
* Visual Studio supported versions Search Order is: VS2013, VS2015, VS2012.
*/
enum VSVERSIONS {
VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"),
VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"),

View File

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

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

View File

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

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

View File

@ -683,7 +683,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
emitImmediate(asm, size, imm);
int nextInsnPos = asm.position();
if (annotateImm && asm.codePatchingAnnotationConsumer != null) {
asm.codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
asm.codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
}
}
@ -700,7 +700,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
emitImmediate(asm, size, imm);
int nextInsnPos = asm.position();
if (annotateImm && asm.codePatchingAnnotationConsumer != null) {
asm.codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
asm.codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
}
}
}
@ -2023,7 +2023,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
emitInt(imm32);
int nextInsnPos = position();
if (annotateImm && codePatchingAnnotationConsumer != null) {
codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
}
}
@ -2201,10 +2201,11 @@ public class AMD64Assembler extends AMD64BaseAssembler {
}
public final void movswl(Register dst, AMD64Address src) {
prefix(src, dst);
emitByte(0x0F);
emitByte(0xBF);
emitOperandHelper(dst, src, 0);
AMD64RMOp.MOVSX.emit(this, DWORD, dst, src);
}
public final void movswq(Register dst, AMD64Address src) {
AMD64RMOp.MOVSX.emit(this, QWORD, dst, src);
}
public final void movw(AMD64Address dst, int imm16) {
@ -2222,6 +2223,13 @@ public class AMD64Assembler extends AMD64BaseAssembler {
emitOperandHelper(src, dst, 0);
}
public final void movw(Register dst, AMD64Address src) {
emitByte(0x66);
prefix(src, dst);
emitByte(0x8B);
emitOperandHelper(dst, src, 0);
}
public final void movzbl(Register dst, AMD64Address src) {
prefix(src, dst);
emitByte(0x0F);
@ -2237,11 +2245,16 @@ public class AMD64Assembler extends AMD64BaseAssembler {
AMD64RMOp.MOVZXB.emit(this, QWORD, dst, src);
}
public final void movzbq(Register dst, AMD64Address src) {
AMD64RMOp.MOVZXB.emit(this, QWORD, dst, src);
}
public final void movzwl(Register dst, AMD64Address src) {
prefix(src, dst);
emitByte(0x0F);
emitByte(0xB7);
emitOperandHelper(dst, src, 0);
AMD64RMOp.MOVZX.emit(this, DWORD, dst, src);
}
public final void movzwq(Register dst, AMD64Address src) {
AMD64RMOp.MOVZX.emit(this, QWORD, dst, src);
}
public final void negl(Register dst) {
@ -2557,16 +2570,63 @@ public class AMD64Assembler extends AMD64BaseAssembler {
emitModRM(dst, src);
}
// Insn: VPMOVZXBW xmm1, xmm2/m64
public final void pmovzxbw(Register dst, AMD64Address src) {
private void pmovSZx(Register dst, AMD64Address src, int op) {
assert supports(CPUFeature.SSE4_1);
assert inRC(XMM, dst);
simdPrefix(dst, Register.None, src, PD, P_0F38, false);
emitByte(0x30);
emitByte(op);
emitOperandHelper(dst, src, 0);
}
public final void pmovsxbw(Register dst, AMD64Address src) {
pmovSZx(dst, src, 0x20);
}
public final void pmovsxbd(Register dst, AMD64Address src) {
pmovSZx(dst, src, 0x21);
}
public final void pmovsxbq(Register dst, AMD64Address src) {
pmovSZx(dst, src, 0x22);
}
public final void pmovsxwd(Register dst, AMD64Address src) {
pmovSZx(dst, src, 0x23);
}
public final void pmovsxwq(Register dst, AMD64Address src) {
pmovSZx(dst, src, 0x24);
}
public final void pmovsxdq(Register dst, AMD64Address src) {
pmovSZx(dst, src, 0x25);
}
// Insn: VPMOVZXBW xmm1, xmm2/m64
public final void pmovzxbw(Register dst, AMD64Address src) {
pmovSZx(dst, src, 0x30);
}
public final void pmovzxbd(Register dst, AMD64Address src) {
pmovSZx(dst, src, 0x31);
}
public final void pmovzxbq(Register dst, AMD64Address src) {
pmovSZx(dst, src, 0x32);
}
public final void pmovzxwd(Register dst, AMD64Address src) {
pmovSZx(dst, src, 0x33);
}
public final void pmovzxwq(Register dst, AMD64Address src) {
pmovSZx(dst, src, 0x34);
}
public final void pmovzxdq(Register dst, AMD64Address src) {
pmovSZx(dst, src, 0x35);
}
public final void pmovzxbw(Register dst, Register src) {
assert supports(CPUFeature.SSE4_1);
assert inRC(XMM, dst) && inRC(XMM, src);
@ -2881,6 +2941,10 @@ public class AMD64Assembler extends AMD64BaseAssembler {
XOR.rmOp.emit(this, DWORD, dst, src);
}
public final void xorq(Register dst, Register src) {
XOR.rmOp.emit(this, QWORD, dst, src);
}
public final void xorpd(Register dst, Register src) {
SSEOp.XOR.emit(this, PD, dst, src);
}
@ -3045,7 +3109,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
emitLong(imm64);
int nextInsnPos = position();
if (annotateImm && codePatchingAnnotationConsumer != null) {
codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
}
}
@ -3189,6 +3253,19 @@ public class AMD64Assembler extends AMD64BaseAssembler {
emitModRM(5, dst);
}
public final void sarq(Register dst, int imm8) {
assert isShiftCount(imm8 >> 1) : "illegal shift count";
prefixq(dst);
if (imm8 == 1) {
emitByte(0xD1);
emitModRM(7, dst);
} else {
emitByte(0xC1);
emitModRM(7, dst);
emitByte(imm8);
}
}
public final void sbbq(Register dst, Register src) {
SBB.rmOp.emit(this, QWORD, dst, src);
}

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

View File

@ -136,9 +136,9 @@ import java.util.List;
import java.util.Map;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.debug.GraalError;
import jdk.vm.ci.code.Register;
@ -1281,7 +1281,7 @@ public abstract class SPARCAssembler extends Assembler {
public int setDisp(int inst, int d) {
assert this.match(inst);
if (!isValidDisp(d)) {
throw new PermanentBailoutException("Too large displacement 0x%x in field %s in instruction %s", d, this.disp, this);
throw new BranchTargetOutOfBoundsException(true, "Too large displacement 0x%x in field %s in instruction %s", d, this.disp, this);
}
return this.disp.setBits(inst, d);
}

View File

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

View File

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

View File

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

View File

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

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));
}
@Override
public Value emitMathLog(Value input, boolean base10) {
throw GraalError.unimplemented();
}
@Override
public Value emitMathCos(Value input) {
throw GraalError.unimplemented();
}
@Override
public Value emitMathSin(Value input) {
throw GraalError.unimplemented();
}
@Override
public Value emitMathTan(Value input) {
throw GraalError.unimplemented();
}
@Override
public void emitCompareOp(AArch64Kind cmpKind, Variable left, Value right) {
throw GraalError.unimplemented();

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.AArch64ControlFlow;
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.BranchOp;
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CompareBranchZeroOp;
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CondMoveOp;
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CondSetOp;
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp;
@ -257,6 +258,27 @@ public abstract class AArch64LIRGenerator extends LIRGenerator {
@Override
public void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
double trueDestinationProbability) {
if (cond == Condition.EQ) {
// emit cbz instruction for IsNullNode.
assert !LIRValueUtil.isNullConstant(left) : "emitNullCheckBranch()'s null input should be in right.";
if (LIRValueUtil.isNullConstant(right)) {
append(new CompareBranchZeroOp(asAllocatable(left), trueDestination, falseDestination, trueDestinationProbability));
return;
}
// emit cbz instruction for IntegerEquals when any of the inputs is zero.
AArch64Kind kind = (AArch64Kind) cmpKind;
if (kind.isInteger()) {
if (isIntConstant(left, 0)) {
append(new CompareBranchZeroOp(asAllocatable(right), trueDestination, falseDestination, trueDestinationProbability));
return;
} else if (isIntConstant(right, 0)) {
append(new CompareBranchZeroOp(asAllocatable(left), trueDestination, falseDestination, trueDestinationProbability));
return;
}
}
}
boolean mirrored = emitCompare(cmpKind, left, right, cond, unorderedIsTrue);
Condition finalCondition = mirrored ? cond.mirror() : cond;
boolean finalUnorderedIsTrue = mirrored ? !unorderedIsTrue : unorderedIsTrue;

View File

@ -37,11 +37,14 @@ import org.graalvm.compiler.core.match.ComplexMatchResult;
import org.graalvm.compiler.core.match.MatchRule;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.lir.LIRFrameState;
import org.graalvm.compiler.lir.LabelRef;
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.DeoptimizingNode;
import org.graalvm.compiler.nodes.IfNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.AddNode;
@ -178,6 +181,28 @@ public class AArch64NodeMatchRules extends NodeMatchRules {
return builder -> getArithmeticLIRGenerator().emitMSub(operand(a), operand(b), operand(c));
}
/**
* ((x & (1 << n)) == 0) -> tbz/tbnz n label.
*/
@MatchRule("(If (IntegerTest value Constant=a))")
public ComplexMatchResult testBitAndBranch(IfNode root, ValueNode value, ConstantNode a) {
if (value.getStackKind().isNumericInteger()) {
long constant = a.asJavaConstant().asLong();
if (Long.bitCount(constant) == 1) {
int bitToTest = Long.numberOfTrailingZeros(constant);
return builder -> {
LabelRef trueDestination = getLIRBlock(root.trueSuccessor());
LabelRef falseDestination = getLIRBlock(root.falseSuccessor());
AllocatableValue src = moveSp(gen.asAllocatable(operand(value)));
double trueDestinationProbability = root.getTrueSuccessorProbability();
gen.append(new AArch64ControlFlow.BitTestAndBranchOp(trueDestination, falseDestination, src, trueDestinationProbability, bitToTest));
return null;
};
}
}
return null;
}
@Override
public AArch64LIRGenerator getLIRGeneratorTool() {
return (AArch64LIRGenerator) gen;

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.
*
* This code is free software; you can redistribute it and/or modify it
@ -80,13 +80,6 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
import static org.graalvm.compiler.lir.amd64.AMD64Arithmetic.DREM;
import static org.graalvm.compiler.lir.amd64.AMD64Arithmetic.FREM;
import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp.BinaryIntrinsicOpcode.POW;
import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.COS;
import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.EXP;
import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.LOG;
import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.LOG10;
import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.SIN;
import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.TAN;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
@ -116,8 +109,13 @@ import org.graalvm.compiler.lir.amd64.AMD64ArithmeticLIRGeneratorTool;
import org.graalvm.compiler.lir.amd64.AMD64Binary;
import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer;
import org.graalvm.compiler.lir.amd64.AMD64ClearRegisterOp;
import org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp;
import org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp;
import org.graalvm.compiler.lir.amd64.AMD64MathCosOp;
import org.graalvm.compiler.lir.amd64.AMD64MathExpOp;
import org.graalvm.compiler.lir.amd64.AMD64MathLog10Op;
import org.graalvm.compiler.lir.amd64.AMD64MathLogOp;
import org.graalvm.compiler.lir.amd64.AMD64MathPowOp;
import org.graalvm.compiler.lir.amd64.AMD64MathSinOp;
import org.graalvm.compiler.lir.amd64.AMD64MathTanOp;
import org.graalvm.compiler.lir.amd64.AMD64Move;
import org.graalvm.compiler.lir.amd64.AMD64MulDivOp;
import org.graalvm.compiler.lir.amd64.AMD64ShiftOp;
@ -127,7 +125,6 @@ import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary;
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary.AVXBinaryOp;
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorUnary;
import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator;
import org.graalvm.compiler.lir.gen.LIRGenerator;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.amd64.AMD64.CPUFeature;
@ -152,41 +149,11 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
private static final RegisterValue RCX_I = AMD64.rcx.asValue(LIRKind.value(AMD64Kind.DWORD));
public AMD64ArithmeticLIRGenerator(AllocatableValue nullRegisterValue, Maths maths) {
public AMD64ArithmeticLIRGenerator(AllocatableValue nullRegisterValue) {
this.nullRegisterValue = nullRegisterValue;
this.maths = maths == null ? new Maths() {
} : maths;
}
private final AllocatableValue nullRegisterValue;
private final Maths maths;
/**
* Interface for emitting LIR for selected {@link Math} routines. A {@code null} return value
* for any method in this interface means the caller must emit the LIR itself.
*/
public interface Maths {
@SuppressWarnings("unused")
default Variable emitLog(LIRGenerator gen, Value input, boolean base10) {
return null;
}
@SuppressWarnings("unused")
default Variable emitCos(LIRGenerator gen, Value input) {
return null;
}
@SuppressWarnings("unused")
default Variable emitSin(LIRGenerator gen, Value input) {
return null;
}
@SuppressWarnings("unused")
default Variable emitTan(LIRGenerator gen, Value input) {
return null;
}
}
@Override
public Variable emitNegate(Value inputVal) {
@ -781,6 +748,7 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
}
}
@Override
public Variable emitRor(Value a, Value b) {
switch ((AMD64Kind) a.getPlatformKind()) {
case DWORD:
@ -1103,65 +1071,36 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
@Override
public Value emitMathLog(Value input, boolean base10) {
LIRGenerator gen = getLIRGen();
Variable result = maths.emitLog(gen, input, base10);
if (result == null) {
result = gen.newVariable(LIRKind.combine(input));
AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), base10 ? LOG10 : LOG, result, asAllocatable(input), stackSlot));
if (base10) {
return new AMD64MathLog10Op().emitLIRWrapper(getLIRGen(), input);
} else {
return new AMD64MathLogOp().emitLIRWrapper(getLIRGen(), input);
}
return result;
}
@Override
public Value emitMathCos(Value input) {
LIRGenerator gen = getLIRGen();
Variable result = maths.emitCos(gen, input);
if (result == null) {
result = gen.newVariable(LIRKind.combine(input));
AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), COS, result, asAllocatable(input), stackSlot));
}
return result;
return new AMD64MathCosOp().emitLIRWrapper(getLIRGen(), input);
}
@Override
public Value emitMathSin(Value input) {
LIRGenerator gen = getLIRGen();
Variable result = maths.emitSin(gen, input);
if (result == null) {
result = gen.newVariable(LIRKind.combine(input));
AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), SIN, result, asAllocatable(input), stackSlot));
}
return result;
return new AMD64MathSinOp().emitLIRWrapper(getLIRGen(), input);
}
@Override
public Value emitMathTan(Value input) {
LIRGenerator gen = getLIRGen();
Variable result = maths.emitTan(gen, input);
if (result == null) {
result = gen.newVariable(LIRKind.combine(input));
AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), TAN, result, asAllocatable(input), stackSlot));
}
return result;
return new AMD64MathTanOp().emitLIRWrapper(getLIRGen(), input);
}
@Override
public Value emitMathExp(Value input) {
Variable result = getLIRGen().newVariable(LIRKind.combine(input));
AllocatableValue stackSlot = getLIRGen().getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
getLIRGen().append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), EXP, result, asAllocatable(input), stackSlot));
return result;
return new AMD64MathExpOp().emitLIRWrapper(getLIRGen(), input);
}
@Override
public Value emitMathPow(Value input1, Value input2) {
Variable result = getLIRGen().newVariable(LIRKind.combine(input1));
getLIRGen().append(new AMD64MathIntrinsicBinaryOp(getAMD64LIRGen(), POW, result, asAllocatable(input1), asAllocatable(input2)));
return result;
public Value emitMathPow(Value x, Value y) {
return new AMD64MathPowOp().emitLIRWrapper(getLIRGen(), x, y);
}
protected AMD64LIRGenerator getAMD64LIRGen() {

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

View File

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

View File

@ -37,9 +37,9 @@ public enum SpeculativeExecutionAttacksMitigations {
public static class Options {
// @formatter:off
@Option(help = "Select a strategy to mitigate speculative execution attacks (e.g., SPECTRE)", type = OptionType.User)
@Option(help = "file:doc-files/MitigateSpeculativeExecutionAttacksHelp.txt")
public static final EnumOptionKey<SpeculativeExecutionAttacksMitigations> MitigateSpeculativeExecutionAttacks = new EnumOptionKey<>(None);
@Option(help = "Use index masking after bounds check to mitigate speculative execution attacks", type = OptionType.User)
@Option(help = "Use index masking after bounds check to mitigate speculative execution attacks.", type = OptionType.User)
public static final OptionKey<Boolean> UseIndexMasking = new OptionKey<>(false);
// @formatter:on
}

View File

@ -24,6 +24,8 @@
package org.graalvm.compiler.core.common.cfg;
import java.util.Comparator;
public abstract class AbstractBlockBase<T extends AbstractBlockBase<T>> {
protected int id;
@ -171,4 +173,13 @@ public abstract class AbstractBlockBase<T extends AbstractBlockBase<T>> {
public int hashCode() {
return id;
}
public static class BlockIdComparator implements Comparator<AbstractBlockBase<?>> {
@Override
public int compare(AbstractBlockBase<?> o1, AbstractBlockBase<?> o2) {
return Integer.compare(o1.getId(), o2.getId());
}
}
public static final BlockIdComparator BLOCK_ID_COMPARATOR = new BlockIdComparator();
}

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();
Loop<?> blockLoop = block.getLoop();

View File

@ -25,19 +25,28 @@
package org.graalvm.compiler.core.common.cfg;
import static org.graalvm.compiler.core.common.cfg.AbstractBlockBase.BLOCK_ID_COMPARATOR;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public abstract class Loop<T extends AbstractBlockBase<T>> {
private final Loop<T> parent;
private final List<Loop<T>> children;
private final ArrayList<Loop<T>> children;
private final int depth;
private final int index;
private final T header;
private final List<T> blocks;
private final List<T> exits;
private final ArrayList<T> blocks;
private final ArrayList<T> exits;
/**
* Natural exits, ignoring LoopExitNodes.
*
* @see #getNaturalExits()
*/
private final ArrayList<T> naturalExits;
protected Loop(Loop<T> parent, int index, T header) {
this.parent = parent;
@ -51,6 +60,7 @@ public abstract class Loop<T extends AbstractBlockBase<T>> {
this.blocks = new ArrayList<>();
this.children = new ArrayList<>();
this.exits = new ArrayList<>();
this.naturalExits = new ArrayList<>();
}
public abstract long numBackedges();
@ -84,12 +94,87 @@ public abstract class Loop<T extends AbstractBlockBase<T>> {
return blocks;
}
public List<T> getExits() {
/**
* Returns the loop exits.
*
* This might be a conservative set: before framestate assignment it matches the LoopExitNodes
* even if earlier blocks could be considered as exits. After framestate assignments, this is
* the same as {@link #getNaturalExits()}.
*
* <p>
* LoopExitNodes are inserted in the control-flow during parsing and are natural exits: they are
* the earliest block at which we are guaranteed to have exited the loop. However, after some
* transformations of the graph, the natural exit might go up but the LoopExitNodes are not
* updated.
* </p>
*
* <p>
* For example in:
*
* <pre>
* for (int i = 0; i < N; i++) {
* if (c) {
* // Block 1
* if (dummy) {
* // ...
* } else {
* // ...
* }
* if (b) {
* continue;
* } else {
* // Block 2
* // LoopExitNode
* break;
* }
* }
* }
* </pre>
*
* After parsing, the natural exits match the LoopExitNode: Block 2 is a natural exit and has a
* LoopExitNode. If the {@code b} condition gets canonicalized to {@code false}, the natural
* exit moves to Block 1 while the LoopExitNode remains in Block 2. In such a scenario,
* {@code getLoopExits()} will contain block 2 while {@link #getNaturalExits()} will contain
* block 1.
*
*
* @see #getNaturalExits()
*/
public List<T> getLoopExits() {
return exits;
}
public void addExit(T t) {
exits.add(t);
public boolean isLoopExit(T block) {
assert isSorted(exits);
return Collections.binarySearch(exits, block, BLOCK_ID_COMPARATOR) >= 0;
}
/**
* Returns the natural exit points: these are the earliest block that are guaranteed to never
* reach a back-edge.
*
* This can not be used in the context of preserving or using loop-closed form.
*
* @see #getLoopExits()
*/
public ArrayList<T> getNaturalExits() {
return naturalExits;
}
public boolean isNaturalExit(T block) {
assert isSorted(naturalExits);
return Collections.binarySearch(naturalExits, block, BLOCK_ID_COMPARATOR) >= 0;
}
private static <T extends AbstractBlockBase<T>> boolean isSorted(List<T> list) {
int lastId = Integer.MIN_VALUE;
for (AbstractBlockBase<?> block : list) {
if (block.getId() < lastId) {
return false;
}
lastId = block.getId();
}
return true;
}
/**
@ -115,4 +200,9 @@ public abstract class Loop<T extends AbstractBlockBase<T>> {
public int hashCode() {
return index + depth * 31;
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
}

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;
}
@Override
public void accept(Visitor v) {
super.accept(v);
v.visitObject(type);
v.visitBoolean(exactType);
}
protected abstract AbstractObjectStamp copyWith(ResolvedJavaType newType, boolean newExactType, boolean newNonNull, boolean newAlwaysNull);
@Override

View File

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

View File

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

View File

@ -31,6 +31,7 @@ import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.MemoryAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.UnresolvedJavaType;
public class ObjectStamp extends AbstractObjectStamp {
@ -92,4 +93,48 @@ public class ObjectStamp extends AbstractObjectStamp {
return null;
}
}
/**
* Convert an ObjectStamp into a representation that can be resolved symbolically into the
* original stamp.
*/
@Override
public SymbolicJVMCIReference<ObjectStamp> makeSymbolic() {
if (type() == null) {
return null;
}
return new SymbolicObjectStamp(this);
}
static class SymbolicObjectStamp implements SymbolicJVMCIReference<ObjectStamp> {
UnresolvedJavaType type;
private boolean exactType;
private boolean nonNull;
private boolean alwaysNull;
SymbolicObjectStamp(ObjectStamp stamp) {
if (stamp.type() != null) {
type = UnresolvedJavaType.create(stamp.type().getName());
}
exactType = stamp.isExactType();
nonNull = stamp.nonNull();
alwaysNull = stamp.alwaysNull();
}
@Override
public ObjectStamp resolve(ResolvedJavaType accessingClass) {
return new ObjectStamp(type != null ? type.resolve(accessingClass) : null, exactType, nonNull, alwaysNull);
}
@Override
public String toString() {
return "SymbolicObjectStamp{" +
"declaringType=" + type +
", exactType=" + exactType +
", nonNull=" + nonNull +
", alwaysNull=" + alwaysNull +
'}';
}
}
}

View File

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

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.spi.LIRKindTool;
import org.graalvm.compiler.serviceprovider.SpeculationReasonGroup.SpeculationContextObject;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.JavaKind;
@ -36,7 +37,7 @@ import jdk.vm.ci.meta.ResolvedJavaType;
/**
* A stamp is the basis for a type system.
*/
public abstract class Stamp {
public abstract class Stamp implements SpeculationContextObject {
protected Stamp() {
}
@ -185,4 +186,15 @@ public abstract class Stamp {
}
return false;
}
/**
* Convert a Stamp into a representation that can be resolved symbolically into the original
* stamp. If this stamp contains no references to JVMCI types then simply return null.
*/
public SymbolicJVMCIReference<? extends Stamp> makeSymbolic() {
return null;
}
@Override
public abstract String toString();
}

View File

@ -24,6 +24,8 @@
package org.graalvm.compiler.core.common.type;
import java.util.Objects;
/**
* A pair of stamp with one being the stamp that can be trusted and the other one being a guess that
* needs a dynamic check to be used.
@ -63,4 +65,22 @@ public final class StampPair {
return trustedStamp + " (unchecked=" + uncheckedStamp + ")";
}
}
@Override
public int hashCode() {
return trustedStamp.hashCode() + 11 + (uncheckedStamp != null ? uncheckedStamp.hashCode() : 0);
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof StampPair) {
StampPair other = (StampPair) obj;
return trustedStamp.equals(other.trustedStamp) && Objects.equals(uncheckedStamp, other.uncheckedStamp);
}
return false;
}
}

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() {
}
@Override
public void accept(Visitor v) {
}
@Override
public Stamp unrestricted() {
return this;

View File

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

View File

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

View File

@ -33,7 +33,7 @@ import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.ConditionalEliminationPhase;
import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase;

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

View File

@ -111,7 +111,7 @@ import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.Phase;
import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
import org.graalvm.compiler.phases.common.inlining.InliningPhase;
import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy;
@ -899,11 +899,21 @@ public abstract class GraalCompilerTest extends GraalTest {
return actual;
}
private static final List<Class<?>> C2_OMIT_STACK_TRACE_IN_FAST_THROW_EXCEPTIONS = Arrays.asList(
ArithmeticException.class,
ArrayIndexOutOfBoundsException.class,
ArrayStoreException.class,
ClassCastException.class,
NullPointerException.class);
protected void assertEquals(Result expect, Result actual) {
if (expect.exception != null) {
Assert.assertTrue("expected " + expect.exception, actual.exception != null);
Assert.assertEquals("Exception class", expect.exception.getClass(), actual.exception.getClass());
Assert.assertEquals("Exception message", expect.exception.getMessage(), actual.exception.getMessage());
// C2 can optimize out the stack trace and message in some cases
if (expect.exception.getMessage() != null || !C2_OMIT_STACK_TRACE_IN_FAST_THROW_EXCEPTIONS.contains(expect.exception.getClass())) {
Assert.assertEquals("Exception message", expect.exception.getMessage(), actual.exception.getMessage());
}
} else {
if (actual.exception != null) {
throw new AssertionError("expected " + expect.returnValue + " but got an exception", actual.exception);

View File

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

View File

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

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.
*
* 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(contains(rootLoop, d, cfg));
Assert.assertTrue(contains(nestedLoop, d, cfg));
Assert.assertEquals(rootExits, rootLoop.getExits().size());
Assert.assertEquals(nestedExits, nestedLoop.getExits().size());
Assert.assertEquals(innerExits, innerMostLoop.getExits().size());
Assert.assertEquals(rootExits, rootLoop.getLoopExits().size());
Assert.assertEquals(nestedExits, nestedLoop.getLoopExits().size());
Assert.assertEquals(innerExits, innerMostLoop.getLoopExits().size());
debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
}

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

View File

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

View File

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

View File

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

View File

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

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() {
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.phases.PhaseSuite;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
import org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase;
import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;

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

View File

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

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

View File

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

View File

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

View File

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

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;
import static org.graalvm.compiler.core.common.Fields.translateInto;
import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere;
import static org.graalvm.compiler.graph.Edges.translateInto;
import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled;
import static org.graalvm.compiler.graph.InputEdges.translateInto;
import static org.graalvm.compiler.graph.Node.WithAllEdges;

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

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

View File

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

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

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