Merge
This commit is contained in:
commit
7d637db80c
@ -54,12 +54,9 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.TriState;
|
||||
|
||||
public class AOTBackend {
|
||||
|
||||
private final Main main;
|
||||
private final OptionValues graalOptions;
|
||||
|
||||
private final HotSpotBackend backend;
|
||||
|
||||
private final HotSpotProviders providers;
|
||||
private final HotSpotCodeCacheProvider codeCache;
|
||||
private final PhaseSuite<HighTierContext> graphBuilderSuite;
|
||||
@ -81,6 +78,10 @@ public class AOTBackend {
|
||||
return graphBuilderSuite;
|
||||
}
|
||||
|
||||
public HotSpotBackend getBackend() {
|
||||
return backend;
|
||||
}
|
||||
|
||||
private Suites getSuites() {
|
||||
// create suites every time, as we modify options for the compiler
|
||||
return backend.getSuites().getDefaultSuites(graalOptions);
|
||||
@ -189,7 +190,7 @@ public class AOTBackend {
|
||||
|
||||
public void printCompiledMethod(HotSpotResolvedJavaMethod resolvedMethod, CompilationResult compResult) {
|
||||
// This is really not installing the method.
|
||||
InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(null, null, compResult), null, null);
|
||||
InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult), null, null);
|
||||
String disassembly = codeCache.disassemble(installedCode);
|
||||
if (disassembly != null) {
|
||||
main.printlnDebug(disassembly);
|
||||
|
@ -145,7 +145,7 @@ public class AOTCompilationTask implements Runnable, Comparable<Object> {
|
||||
aotBackend.printCompiledMethod((HotSpotResolvedJavaMethod) method, compResult);
|
||||
}
|
||||
|
||||
result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method));
|
||||
result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method, aotBackend.getBackend()));
|
||||
}
|
||||
|
||||
private String getMethodDescription() {
|
||||
|
@ -24,6 +24,7 @@
|
||||
package jdk.tools.jaotc;
|
||||
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.core.target.Backend;
|
||||
import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
|
||||
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
|
||||
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
|
||||
@ -31,9 +32,11 @@ import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
|
||||
public class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo {
|
||||
|
||||
private final HotSpotResolvedJavaMethod method;
|
||||
private final Backend backend;
|
||||
|
||||
public AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method) {
|
||||
public AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method, Backend backend) {
|
||||
this.method = method;
|
||||
this.backend = backend;
|
||||
}
|
||||
|
||||
public String getSymbolName() {
|
||||
@ -46,7 +49,7 @@ public class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo {
|
||||
}
|
||||
|
||||
public HotSpotCompiledCode compiledCode(CompilationResult result) {
|
||||
return HotSpotCompiledCodeBuilder.createCompiledCode(method, null, result);
|
||||
return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), method, null, result);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ public class AOTStub implements JavaMethodInfo {
|
||||
}
|
||||
|
||||
public HotSpotCompiledCode compiledCode(CompilationResult result) {
|
||||
return HotSpotCompiledCodeBuilder.createCompiledCode(null, null, result);
|
||||
return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), null, null, result);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,15 +22,16 @@
|
||||
*/
|
||||
package org.graalvm.compiler.api.directives.test;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||
import org.graalvm.compiler.nodes.AbstractBeginNode;
|
||||
import org.graalvm.compiler.nodes.IfNode;
|
||||
import org.graalvm.compiler.nodes.ReturnNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ProbabilityDirectiveTest extends GraalCompilerTest {
|
||||
|
||||
@ -55,9 +56,21 @@ public class ProbabilityDirectiveTest extends GraalCompilerTest {
|
||||
Assert.assertEquals("IfNode count", 1, ifNodes.count());
|
||||
|
||||
IfNode ifNode = ifNodes.first();
|
||||
AbstractBeginNode trueSuccessor = ifNode.trueSuccessor();
|
||||
Assert.assertEquals("branch probability of " + ifNode, 0.125, ifNode.probability(trueSuccessor), 0);
|
||||
AbstractBeginNode oneSuccessor;
|
||||
if (returnValue(ifNode.trueSuccessor()) == 1) {
|
||||
oneSuccessor = ifNode.trueSuccessor();
|
||||
} else {
|
||||
assert returnValue(ifNode.falseSuccessor()) == 1;
|
||||
oneSuccessor = ifNode.falseSuccessor();
|
||||
}
|
||||
Assert.assertEquals("branch probability of " + ifNode, 0.125, ifNode.probability(oneSuccessor), 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int returnValue(AbstractBeginNode b) {
|
||||
ControlFlowAnchorNode anchor = (ControlFlowAnchorNode) b.next();
|
||||
ReturnNode returnNode = (ReturnNode) anchor.next();
|
||||
return returnNode.result().asJavaConstant().asInt();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2017, 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
|
||||
@ -1757,6 +1757,10 @@ public abstract class SPARCAssembler extends Assembler {
|
||||
return constant.isNull() || isSimm(constant.asLong(), 5);
|
||||
}
|
||||
|
||||
public static boolean isSimm5(long imm) {
|
||||
return isSimm(imm, 5);
|
||||
}
|
||||
|
||||
public static boolean isSimm13(int imm) {
|
||||
return isSimm(imm, 13);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public final class TraceStatisticsPrinter {
|
||||
@SuppressWarnings("try")
|
||||
public static void printTraceStatistics(TraceBuilderResult result, String compilationUnitName) {
|
||||
try (Scope s = Debug.scope("DumpTraceStatistics")) {
|
||||
if (Debug.isLogEnabled(Debug.VERBOSE_LOG_LEVEL)) {
|
||||
if (Debug.isLogEnabled(Debug.VERBOSE_LEVEL)) {
|
||||
print(result, compilationUnitName);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
@ -48,9 +48,9 @@ public final class TraceStatisticsPrinter {
|
||||
List<Trace> traces = result.getTraces();
|
||||
int numTraces = traces.size();
|
||||
|
||||
try (Indent indent0 = Debug.logAndIndent(Debug.VERBOSE_LOG_LEVEL, "<tracestatistics>")) {
|
||||
Debug.log(Debug.VERBOSE_LOG_LEVEL, "<name>%s</name>", compilationUnitName != null ? compilationUnitName : "null");
|
||||
try (Indent indent1 = Debug.logAndIndent(Debug.VERBOSE_LOG_LEVEL, "<traces>")) {
|
||||
try (Indent indent0 = Debug.logAndIndent(Debug.VERBOSE_LEVEL, "<tracestatistics>")) {
|
||||
Debug.log(Debug.VERBOSE_LEVEL, "<name>%s</name>", compilationUnitName != null ? compilationUnitName : "null");
|
||||
try (Indent indent1 = Debug.logAndIndent(Debug.VERBOSE_LEVEL, "<traces>")) {
|
||||
printRawLine("tracenumber", "total", "min", "max", "numBlocks");
|
||||
for (int i = 0; i < numTraces; i++) {
|
||||
AbstractBlockBase<?>[] t = traces.get(i).getBlocks();
|
||||
@ -70,14 +70,14 @@ public final class TraceStatisticsPrinter {
|
||||
printLine(i, total, min, max, t.length);
|
||||
}
|
||||
}
|
||||
Debug.log(Debug.VERBOSE_LOG_LEVEL, "</traces>");
|
||||
Debug.log(Debug.VERBOSE_LEVEL, "</traces>");
|
||||
}
|
||||
Debug.log(Debug.VERBOSE_LOG_LEVEL, "</tracestatistics>");
|
||||
Debug.log(Debug.VERBOSE_LEVEL, "</tracestatistics>");
|
||||
|
||||
}
|
||||
|
||||
private static void printRawLine(Object tracenr, Object totalTime, Object minProb, Object maxProb, Object numBlocks) {
|
||||
Debug.log(Debug.VERBOSE_LOG_LEVEL, "%s", String.join(SEP, tracenr.toString(), totalTime.toString(), minProb.toString(), maxProb.toString(), numBlocks.toString()));
|
||||
Debug.log(Debug.VERBOSE_LEVEL, "%s", String.join(SEP, tracenr.toString(), totalTime.toString(), minProb.toString(), maxProb.toString(), numBlocks.toString()));
|
||||
}
|
||||
|
||||
private static void printLine(int tracenr, double totalTime, double minProb, double maxProb, int numBlocks) {
|
||||
|
@ -343,6 +343,33 @@ public enum Condition {
|
||||
if (lt instanceof PrimitiveConstant) {
|
||||
PrimitiveConstant lp = (PrimitiveConstant) lt;
|
||||
PrimitiveConstant rp = (PrimitiveConstant) rt;
|
||||
return foldCondition(lp, rp, unorderedIsTrue);
|
||||
} else {
|
||||
Boolean equal = constantReflection.constantEquals(lt, rt);
|
||||
if (equal == null) {
|
||||
throw new GraalError("could not fold %s %s %s", lt, this, rt);
|
||||
}
|
||||
switch (this) {
|
||||
case EQ:
|
||||
return equal.booleanValue();
|
||||
case NE:
|
||||
return !equal.booleanValue();
|
||||
default:
|
||||
throw new GraalError("expected condition: %s", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to fold a comparison between two primitive constants and return the result.
|
||||
*
|
||||
* @param lp the constant on the left side of the comparison
|
||||
* @param rp the constant on the right side of the comparison
|
||||
* @param unorderedIsTrue true if an undecided float comparison should result in "true"
|
||||
* @return true if the comparison is known to be true, false if the comparison is known to be
|
||||
* false
|
||||
*/
|
||||
public boolean foldCondition(PrimitiveConstant lp, PrimitiveConstant rp, boolean unorderedIsTrue) {
|
||||
switch (lp.getJavaKind()) {
|
||||
case Boolean:
|
||||
case Byte:
|
||||
@ -453,20 +480,6 @@ public enum Condition {
|
||||
default:
|
||||
throw new GraalError("expected value kind %s while folding condition: %s", lp.getJavaKind(), this);
|
||||
}
|
||||
} else {
|
||||
Boolean equal = constantReflection.constantEquals(lt, rt);
|
||||
if (equal == null) {
|
||||
throw new GraalError("could not fold %s %s %s", lt, this, rt);
|
||||
}
|
||||
switch (this) {
|
||||
case EQ:
|
||||
return equal.booleanValue();
|
||||
case NE:
|
||||
return !equal.booleanValue();
|
||||
default:
|
||||
throw new GraalError("expected condition: %s", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Condition join(Condition other) {
|
||||
|
@ -154,6 +154,7 @@ public class FloatStamp extends PrimitiveStamp {
|
||||
return Double.isNaN(lowerBound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnrestricted() {
|
||||
return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN;
|
||||
}
|
||||
|
@ -58,6 +58,11 @@ public final class IllegalStamp extends Stamp {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnrestricted() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stamp empty() {
|
||||
return this;
|
||||
|
@ -254,6 +254,7 @@ public final class IntegerStamp extends PrimitiveStamp {
|
||||
return upMask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnrestricted() {
|
||||
return lowerBound == CodeUtil.minValue(getBits()) && upperBound == CodeUtil.maxValue(getBits()) && downMask == 0 && upMask == CodeUtil.mask(getBits());
|
||||
}
|
||||
|
@ -125,6 +125,13 @@ public abstract class Stamp {
|
||||
return !hasValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether this stamp represents all values of this kind.
|
||||
*/
|
||||
public boolean isUnrestricted() {
|
||||
return this.equals(this.unrestricted());
|
||||
}
|
||||
|
||||
/**
|
||||
* If this stamp represents a single value, the methods returns this single value. It returns
|
||||
* null otherwise.
|
||||
|
@ -39,33 +39,6 @@ import jdk.vm.ci.meta.Signature;
|
||||
|
||||
public class StampFactory {
|
||||
|
||||
/*
|
||||
* The marker stamp for node intrinsics must be its own class, so that it is never equal() to a
|
||||
* regular ObjectStamp.
|
||||
*/
|
||||
static final class NodeIntrinsicStamp extends ObjectStamp {
|
||||
protected static final Stamp SINGLETON = new NodeIntrinsicStamp();
|
||||
|
||||
private NodeIntrinsicStamp() {
|
||||
super(null, false, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return System.identityHashCode(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return this == obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NodeIntrinsicStamp";
|
||||
}
|
||||
}
|
||||
|
||||
// JaCoCo Exclude
|
||||
|
||||
private static final Stamp[] stampCache = new Stamp[JavaKind.values().length];
|
||||
@ -143,14 +116,6 @@ public class StampFactory {
|
||||
return VoidStamp.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* A stamp used only in the graph of intrinsics, e.g., snippets. It is then replaced by an
|
||||
* actual stamp when the intrinsic is used, i.e., when the snippet template is instantiated.
|
||||
*/
|
||||
public static Stamp forNodeIntrinsic() {
|
||||
return NodeIntrinsicStamp.SINGLETON;
|
||||
}
|
||||
|
||||
public static Stamp intValue() {
|
||||
return forKind(JavaKind.Int);
|
||||
}
|
||||
|
@ -45,6 +45,11 @@ public final class VoidStamp extends Stamp {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnrestricted() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaKind getStackKind() {
|
||||
return JavaKind.Void;
|
||||
|
@ -23,10 +23,10 @@
|
||||
package org.graalvm.compiler.core.common.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.graalvm.util.EconomicMap;
|
||||
import org.graalvm.util.Equivalence;
|
||||
|
||||
/**
|
||||
* Creates an array of T objects order by the occurrence frequency of each object. The most
|
||||
@ -49,24 +49,24 @@ public class FrequencyEncoder<T> {
|
||||
}
|
||||
}
|
||||
|
||||
protected final Map<T, Entry<T>> map;
|
||||
protected final EconomicMap<T, Entry<T>> map;
|
||||
protected boolean containsNull;
|
||||
|
||||
/**
|
||||
* Creates an encoder that uses object identity.
|
||||
*/
|
||||
public static <T> FrequencyEncoder<T> createIdentityEncoder() {
|
||||
return new FrequencyEncoder<>(new IdentityHashMap<>());
|
||||
return new FrequencyEncoder<>(EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an encoder that uses {@link Object#equals(Object) object equality}.
|
||||
*/
|
||||
public static <T> FrequencyEncoder<T> createEqualityEncoder() {
|
||||
return new FrequencyEncoder<>(new HashMap<>());
|
||||
return new FrequencyEncoder<>(EconomicMap.create(Equivalence.DEFAULT));
|
||||
}
|
||||
|
||||
protected FrequencyEncoder(Map<T, Entry<T>> map) {
|
||||
protected FrequencyEncoder(EconomicMap<T, Entry<T>> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ public class FrequencyEncoder<T> {
|
||||
* Returns the index of an object in the array. The object must have been
|
||||
* {@link #addObject(Object) added} before.
|
||||
*/
|
||||
public int getIndex(Object object) {
|
||||
public int getIndex(T object) {
|
||||
if (object == null) {
|
||||
assert containsNull;
|
||||
return 0;
|
||||
@ -114,7 +114,10 @@ public class FrequencyEncoder<T> {
|
||||
*/
|
||||
public T[] encodeAll(T[] allObjects) {
|
||||
assert allObjects.length == getLength();
|
||||
List<Entry<T>> sortedEntries = new ArrayList<>(map.values());
|
||||
List<Entry<T>> sortedEntries = new ArrayList<>(allObjects.length);
|
||||
for (Entry<T> value : map.getValues()) {
|
||||
sortedEntries.add(value);
|
||||
}
|
||||
sortedEntries.sort((e1, e2) -> -Integer.compare(e1.frequency, e2.frequency));
|
||||
|
||||
int offset = 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2017, 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
|
||||
@ -202,7 +202,7 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator {
|
||||
|
||||
private Variable emitUnary(Op3s op3, Value input) {
|
||||
Variable result = getLIRGen().newVariable(LIRKind.combine(input));
|
||||
getLIRGen().append(SPARCOP3Op.newUnary(op3, input, result));
|
||||
getLIRGen().append(SPARCOP3Op.newUnary(op3, getLIRGen().loadSimm13(input), result));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -227,9 +227,9 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator {
|
||||
private Variable emitBinary(ValueKind<?> resultKind, Op3s op3, Value a, Value b, LIRFrameState state) {
|
||||
Variable result = getLIRGen().newVariable(resultKind);
|
||||
if (op3.isCommutative() && isJavaConstant(a) && getLIRGen().getMoveFactory().canInlineConstant(asJavaConstant(a))) {
|
||||
getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(b), a, result, state));
|
||||
getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(b), getLIRGen().loadSimm13(a), result, state));
|
||||
} else {
|
||||
getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(a), b, result, state));
|
||||
getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(a), getLIRGen().loadSimm13(b), result, state));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2017, 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
|
||||
@ -199,11 +199,11 @@ public abstract class SPARCLIRGenerator extends LIRGenerator {
|
||||
Condition actualCondition;
|
||||
if (isJavaConstant(x)) {
|
||||
left = load(y);
|
||||
right = loadNonConst(x);
|
||||
right = loadSimm13(x);
|
||||
actualCondition = cond.mirror();
|
||||
} else {
|
||||
left = load(x);
|
||||
right = loadNonConst(y);
|
||||
right = loadSimm13(y);
|
||||
actualCondition = cond;
|
||||
}
|
||||
SPARCKind actualCmpKind = (SPARCKind) cmpKind;
|
||||
@ -250,7 +250,7 @@ public abstract class SPARCLIRGenerator extends LIRGenerator {
|
||||
return load(value);
|
||||
}
|
||||
|
||||
private Value loadSimm13(Value value) {
|
||||
public Value loadSimm13(Value value) {
|
||||
if (isJavaConstant(value)) {
|
||||
JavaConstant c = asJavaConstant(value);
|
||||
if (c.isNull() || SPARCAssembler.isSimm13(c)) {
|
||||
@ -260,6 +260,13 @@ public abstract class SPARCLIRGenerator extends LIRGenerator {
|
||||
return load(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value loadNonConst(Value value) {
|
||||
// SPARC does not support a proper way of loadNonConst. Please use the appropriate
|
||||
// loadSimm11 or loadSimm13 variants.
|
||||
throw GraalError.shouldNotReachHere("This operation is not available for SPARC.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variable emitConditionalMove(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
|
||||
// Emit compare
|
||||
|
@ -22,10 +22,6 @@
|
||||
*/
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.loop.DefaultLoopPolicies;
|
||||
import org.graalvm.compiler.loop.phases.LoopPeelingPhase;
|
||||
import org.graalvm.compiler.nodes.ReturnNode;
|
||||
@ -37,6 +33,9 @@ import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
|
||||
import org.graalvm.compiler.phases.common.inlining.InliningPhase;
|
||||
import org.graalvm.compiler.phases.tiers.HighTierContext;
|
||||
import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* In the following tests, the usages of local variable "a" are replaced with the integer constant
|
||||
@ -162,7 +161,7 @@ public class BoxingEliminationTest extends GraalCompilerTest {
|
||||
sum0 = a;
|
||||
} else {
|
||||
int sum = a;
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int i = 1; i < n; i++) {
|
||||
sum += i;
|
||||
}
|
||||
sum0 = sum;
|
||||
|
@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2014, 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.StructuredGraph.AllowAssumptions;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
|
||||
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
|
||||
import org.graalvm.compiler.phases.tiers.PhaseContext;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
public class CompareCanonicalizerTest3 extends GraalCompilerTest {
|
||||
|
||||
@SuppressWarnings("unused") private static int sink0;
|
||||
@SuppressWarnings("unused") private static int sink1;
|
||||
|
||||
@Test
|
||||
public void test00() {
|
||||
assertCanonicallyEqual("integerTestCanonicalization00", "referenceSnippet00");
|
||||
}
|
||||
|
||||
public static void integerTestCanonicalization00(char a) {
|
||||
if (a - 1 < a) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static void referenceSnippet00(char a) {
|
||||
sink1 = 0;
|
||||
}
|
||||
|
||||
@Ignore("Needs better stamp support for unsigned ranges")
|
||||
@Test
|
||||
public void test01() {
|
||||
assertCanonicallyEqual("integerTestCanonicalization01", "referenceSnippet01");
|
||||
}
|
||||
|
||||
public static void integerTestCanonicalization01(char a) {
|
||||
if (Integer.compareUnsigned(a - 1, a) < 0) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void referenceSnippet01(char a) {
|
||||
if (a != 0) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore("Needs better stamp support for unsigned ranges")
|
||||
@Test
|
||||
public void test1() {
|
||||
assertCanonicallyEqual("integerTestCanonicalization1", "referenceSnippet1");
|
||||
}
|
||||
|
||||
public static void integerTestCanonicalization1(char a) {
|
||||
if (Integer.compareUnsigned(a - 2, a) < 0) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void referenceSnippet1(char a) {
|
||||
if (Integer.compareUnsigned(a, 2) >= 0) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
assertCanonicallyEqual("integerTestCanonicalization2", "referenceSnippet2");
|
||||
}
|
||||
|
||||
public static void integerTestCanonicalization2(int a) {
|
||||
if (a - 1 < a) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void referenceSnippet2(int a) {
|
||||
if (a != Integer.MIN_VALUE) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test3() {
|
||||
assertCanonicallyEqual("integerTestCanonicalization3", "referenceSnippet3");
|
||||
}
|
||||
|
||||
public static void integerTestCanonicalization3(int a) {
|
||||
if (a - 2 < a) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void referenceSnippet3(int a) {
|
||||
if (a >= Integer.MIN_VALUE + 2) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test4() {
|
||||
assertCanonicallyEqual("integerTestCanonicalization4", "referenceSnippet4");
|
||||
}
|
||||
|
||||
public static void integerTestCanonicalization4(int a) {
|
||||
if (a + 1 < a) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void referenceSnippet4(int a) {
|
||||
if (a == Integer.MAX_VALUE) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test5() {
|
||||
assertCanonicallyEqual("integerTestCanonicalization5", "referenceSnippet5");
|
||||
}
|
||||
|
||||
public static void integerTestCanonicalization5(int a) {
|
||||
if (a + 2 < a) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void referenceSnippet5(int a) {
|
||||
if (a > Integer.MAX_VALUE - 2) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test6() {
|
||||
assertCanonicallyEqual("integerTestCanonicalization6", "referenceSnippet6");
|
||||
}
|
||||
|
||||
public static void integerTestCanonicalization6(int a) {
|
||||
if (a < a + 1) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void referenceSnippet6(int a) {
|
||||
if (a != Integer.MAX_VALUE) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test7() {
|
||||
assertCanonicallyEqual("integerTestCanonicalization7", "referenceSnippet7");
|
||||
}
|
||||
|
||||
public static void integerTestCanonicalization7(int a) {
|
||||
if (a < a + 2) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void referenceSnippet7(int a) {
|
||||
if (a <= Integer.MAX_VALUE - 2) {
|
||||
sink1 = 0;
|
||||
} else {
|
||||
sink0 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
protected void assertCanonicallyEqual(String snippet, String reference) {
|
||||
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
|
||||
PhaseContext context = new PhaseContext(getProviders());
|
||||
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
|
||||
canonicalizer.apply(graph, context);
|
||||
canonicalizer.apply(graph, context);
|
||||
StructuredGraph referenceGraph = parseEager(reference, AllowAssumptions.YES);
|
||||
canonicalizer.apply(referenceGraph, context);
|
||||
canonicalizer.apply(referenceGraph, context);
|
||||
assertEquals(referenceGraph, graph, true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
|
||||
return InlineInvokePlugin.InlineInfo.createStandardInlineInfo(method);
|
||||
}
|
||||
}
|
@ -32,8 +32,8 @@ import org.junit.Test;
|
||||
public class ConditionalEliminationMulTest extends GraalCompilerTest {
|
||||
|
||||
public static void snippet01(int a) {
|
||||
if (a == 2) {
|
||||
if (a * 3 != 6) {
|
||||
if (a == 3) {
|
||||
if (a * 11 != 33) {
|
||||
shouldBeOptimizedAway();
|
||||
}
|
||||
}
|
||||
@ -41,7 +41,7 @@ public class ConditionalEliminationMulTest extends GraalCompilerTest {
|
||||
|
||||
public static void snippet02(int a) {
|
||||
if (a == 0) {
|
||||
if (a * 3 != 0) {
|
||||
if (a * 11 != 0) {
|
||||
shouldBeOptimizedAway();
|
||||
}
|
||||
}
|
||||
|
@ -22,9 +22,8 @@
|
||||
*/
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Collection of tests for
|
||||
@ -32,15 +31,16 @@ import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
* that triggered bugs in this phase.
|
||||
*/
|
||||
public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase {
|
||||
protected static int sink3;
|
||||
|
||||
private static final String REFERENCE_SNIPPET = "referenceSnippet";
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public static int referenceSnippet(int a) {
|
||||
public static void referenceSnippet(int a) {
|
||||
if (a == 0) {
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
return 0;
|
||||
sink0 = 0;
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -49,21 +49,21 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public static int test1Snippet(int a) {
|
||||
public static void test1Snippet(int a) {
|
||||
if (a == 0) {
|
||||
if (a == 5) {
|
||||
return 100;
|
||||
sink2 = 100;
|
||||
}
|
||||
if (a > 100) {
|
||||
if (a == 0) {
|
||||
return 200;
|
||||
sink3 = 200;
|
||||
}
|
||||
}
|
||||
if (a != 2) {
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
sink0 = 0;
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -72,18 +72,18 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public static int test2Snippet(int a) {
|
||||
public static void test2Snippet(int a) {
|
||||
if (a == 0) {
|
||||
if (a > 100) {
|
||||
if (a == 0) {
|
||||
return 200;
|
||||
sink3 = 200;
|
||||
}
|
||||
}
|
||||
if (a != 2) {
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
sink0 = 0;
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -92,7 +92,7 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public static int test3Snippet(int a) {
|
||||
public static void test3Snippet(int a) {
|
||||
if (a == 0) {
|
||||
if (a < 1) {
|
||||
if (a < 2) {
|
||||
@ -101,9 +101,9 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase
|
||||
if (a > -2) {
|
||||
if (a > -3) {
|
||||
if (a == 1) {
|
||||
return 42;
|
||||
sink2 = 42;
|
||||
} else {
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -112,18 +112,18 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
sink0 = 0;
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public static int test4Snippet(int a, int b) {
|
||||
public static void test4Snippet(int a, int b) {
|
||||
if (b < 1) {
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
if (b < 0) {
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
sink0 = 0;
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -132,21 +132,21 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public static int test5Snippet(int a, int b) {
|
||||
public static void test5Snippet(int a, int b) {
|
||||
if ((b & 3) == 0) {
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
if ((b & 7) == 0) {
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
} else {
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
if ((b & 1) == 0) {
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
return 2;
|
||||
sink2 = 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
sink0 = 0;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -22,22 +22,16 @@
|
||||
*/
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
|
||||
/**
|
||||
* Collection of tests for
|
||||
* {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those
|
||||
* that triggered bugs in this phase.
|
||||
*/
|
||||
public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase {
|
||||
public ConditionalEliminationTest11() {
|
||||
// Don't disable simplification
|
||||
super(false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public static int referenceSnippet(int a) {
|
||||
if ((a & 15) != 15) {
|
||||
|
@ -34,13 +34,6 @@ import org.junit.Test;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
public class ConditionalEliminationTest13 extends ConditionalEliminationTestBase {
|
||||
public ConditionalEliminationTest13() {
|
||||
super(false);
|
||||
}
|
||||
|
||||
private static int sink0;
|
||||
private static int sink1;
|
||||
private static int sink2;
|
||||
|
||||
@Override
|
||||
protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
|
||||
@ -317,7 +310,7 @@ public class ConditionalEliminationTest13 extends ConditionalEliminationTestBase
|
||||
super.prepareGraph(graph, canonicalizer, context, applyLowering);
|
||||
graph.clearAllStateAfter();
|
||||
graph.setGuardsStage(StructuredGraph.GuardsStage.AFTER_FSA);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After preparation");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "After preparation");
|
||||
canonicalizer.apply(graph, context);
|
||||
}
|
||||
}
|
||||
|
@ -22,11 +22,10 @@
|
||||
*/
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
|
||||
/**
|
||||
* Collection of tests for
|
||||
* {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those
|
||||
@ -50,20 +49,20 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase
|
||||
static final class DistinctB {
|
||||
}
|
||||
|
||||
public static int reference1Snippet(Object a) {
|
||||
public static void reference1Snippet(Object a) {
|
||||
if (a instanceof B) {
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
return 2;
|
||||
sink2 = 2;
|
||||
}
|
||||
|
||||
public static int test1Snippet(Object a) {
|
||||
public static void test1Snippet(Object a) {
|
||||
if (a instanceof B) {
|
||||
if (a instanceof A) {
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
}
|
||||
return 2;
|
||||
sink2 = 2;
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -71,21 +70,21 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase
|
||||
testConditionalElimination("test1Snippet", "reference1Snippet");
|
||||
}
|
||||
|
||||
public static int reference2Snippet(A a) {
|
||||
public static void reference2Snippet(A a) {
|
||||
if (a instanceof B) {
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
return 2;
|
||||
sink2 = 2;
|
||||
}
|
||||
|
||||
public static int test2Snippet(A a) {
|
||||
public static void test2Snippet(A a) {
|
||||
if (a instanceof B) {
|
||||
B newVal = (B) a;
|
||||
if (newVal != null) {
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
}
|
||||
return 2;
|
||||
sink2 = 2;
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -94,28 +93,28 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static int reference3Snippet(Object a, Object b) {
|
||||
public static void reference3Snippet(Object a, Object b) {
|
||||
if (a instanceof DistinctA) {
|
||||
DistinctA proxyA = (DistinctA) a;
|
||||
if (b instanceof DistinctB) {
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
}
|
||||
return 2;
|
||||
sink2 = 2;
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public static int test3Snippet(Object a, Object b) {
|
||||
public static void test3Snippet(Object a, Object b) {
|
||||
if (a instanceof DistinctA) {
|
||||
DistinctA proxyA = (DistinctA) a;
|
||||
if (b instanceof DistinctB) {
|
||||
if (proxyA == b) {
|
||||
return 42;
|
||||
sink0 = 42;
|
||||
}
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
}
|
||||
return 2;
|
||||
sink2 = 2;
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -123,54 +122,54 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase
|
||||
testConditionalElimination("test3Snippet", "reference3Snippet", true, false);
|
||||
}
|
||||
|
||||
public static int reference4Snippet(Object a) {
|
||||
public static void reference4Snippet(Object a) {
|
||||
if (!(a instanceof B)) {
|
||||
GraalDirectives.deoptimizeAndInvalidate();
|
||||
}
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
|
||||
public static int test4Snippet1(Object a) {
|
||||
public static void test4Snippet1(Object a) {
|
||||
if (!(a instanceof B)) {
|
||||
GraalDirectives.deoptimizeAndInvalidate();
|
||||
}
|
||||
if (!(a instanceof A)) {
|
||||
GraalDirectives.deoptimizeAndInvalidate();
|
||||
}
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
|
||||
public static int test4Snippet2(Object a) {
|
||||
public static void test4Snippet2(Object a) {
|
||||
if (!(a instanceof A)) {
|
||||
GraalDirectives.deoptimizeAndInvalidate();
|
||||
}
|
||||
if (!(a instanceof B)) {
|
||||
GraalDirectives.deoptimizeAndInvalidate();
|
||||
}
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"cast", "unused"})
|
||||
public static int test4Snippet3(Object a) {
|
||||
public static void test4Snippet3(Object a) {
|
||||
Object pi = (A) a;
|
||||
if (!(a instanceof B)) {
|
||||
GraalDirectives.deoptimizeAndInvalidate();
|
||||
}
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
|
||||
public static int test4Snippet4(Object a) {
|
||||
public static void test4Snippet4(Object a) {
|
||||
if (!(a instanceof A)) {
|
||||
GraalDirectives.deoptimizeAndInvalidate();
|
||||
}
|
||||
if (!(((A) a) instanceof B)) {
|
||||
GraalDirectives.deoptimizeAndInvalidate();
|
||||
}
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"cast"})
|
||||
public static int test4Snippet5(Object a) {
|
||||
public static void test4Snippet5(Object a) {
|
||||
Object pi = (A) a;
|
||||
if (pi == null) {
|
||||
GraalDirectives.deoptimizeAndInvalidate();
|
||||
@ -178,7 +177,7 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase
|
||||
if (!(a instanceof B)) {
|
||||
GraalDirectives.deoptimizeAndInvalidate();
|
||||
}
|
||||
return 1;
|
||||
sink1 = 1;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -42,15 +42,9 @@ import org.junit.Assert;
|
||||
* that triggered bugs in this phase.
|
||||
*/
|
||||
public class ConditionalEliminationTestBase extends GraalCompilerTest {
|
||||
private final boolean disableSimplification;
|
||||
|
||||
protected ConditionalEliminationTestBase() {
|
||||
this(true);
|
||||
}
|
||||
|
||||
protected ConditionalEliminationTestBase(boolean disableSimplification) {
|
||||
this.disableSimplification = disableSimplification;
|
||||
}
|
||||
protected static int sink0;
|
||||
protected static int sink1;
|
||||
protected static int sink2;
|
||||
|
||||
protected void testConditionalElimination(String snippet, String referenceSnippet) {
|
||||
testConditionalElimination(snippet, referenceSnippet, false, false);
|
||||
@ -59,15 +53,9 @@ public class ConditionalEliminationTestBase extends GraalCompilerTest {
|
||||
@SuppressWarnings("try")
|
||||
protected void testConditionalElimination(String snippet, String referenceSnippet, boolean applyConditionalEliminationOnReference, boolean applyLowering) {
|
||||
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
PhaseContext context = new PhaseContext(getProviders());
|
||||
CanonicalizerPhase canonicalizer1 = new CanonicalizerPhase();
|
||||
if (disableSimplification) {
|
||||
/**
|
||||
* Some tests break if simplification is done so only do it when needed.
|
||||
*/
|
||||
canonicalizer1.disableSimplification();
|
||||
}
|
||||
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
|
||||
try (Debug.Scope scope = Debug.scope("ConditionalEliminationTest", graph)) {
|
||||
prepareGraph(graph, canonicalizer1, context, applyLowering);
|
||||
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.StructuredGraph.AllowAssumptions;
|
||||
import org.graalvm.compiler.nodes.calc.AndNode;
|
||||
import org.graalvm.compiler.nodes.calc.NotNode;
|
||||
import org.graalvm.compiler.nodes.calc.OrNode;
|
||||
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DeMorganCanonicalizationTest extends GraalCompilerTest {
|
||||
|
||||
public static int or(int a, int b) {
|
||||
return ~a | ~b;
|
||||
}
|
||||
|
||||
public static int and(int a, int b) {
|
||||
return ~a & ~b;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnd() {
|
||||
StructuredGraph g = parseEager("and", AllowAssumptions.NO, getInitialOptions());
|
||||
new CanonicalizerPhase().apply(g, getDefaultHighTierContext());
|
||||
Assert.assertEquals(1, g.getNodes().filter(OrNode.class).count());
|
||||
Assert.assertEquals(1, g.getNodes().filter(NotNode.class).count());
|
||||
|
||||
testAgainstExpected(g.method(), new Result(and(-1, 17), null), (Object) null, -1, 17);
|
||||
testAgainstExpected(g.method(), new Result(and(-1, 1), null), (Object) null, -1, 1);
|
||||
testAgainstExpected(g.method(), new Result(and(-1, -1), null), (Object) null, -1, -1);
|
||||
testAgainstExpected(g.method(), new Result(and(Integer.MIN_VALUE, Integer.MIN_VALUE), null), (Object) null, Integer.MIN_VALUE, Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOr() {
|
||||
StructuredGraph g = parseEager("or", AllowAssumptions.NO, getInitialOptions());
|
||||
new CanonicalizerPhase().apply(g, getDefaultHighTierContext());
|
||||
Assert.assertEquals(1, g.getNodes().filter(AndNode.class).count());
|
||||
Assert.assertEquals(1, g.getNodes().filter(NotNode.class).count());
|
||||
|
||||
testAgainstExpected(g.method(), new Result(or(-1, 17), null), (Object) null, -1, 17);
|
||||
testAgainstExpected(g.method(), new Result(or(-1, 1), null), (Object) null, -1, 1);
|
||||
testAgainstExpected(g.method(), new Result(or(-1, -1), null), (Object) null, -1, -1);
|
||||
testAgainstExpected(g.method(), new Result(or(Integer.MIN_VALUE, Integer.MIN_VALUE), null), (Object) null, Integer.MIN_VALUE, Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
}
|
@ -86,9 +86,9 @@ public class DegeneratedLoopsTest extends GraalCompilerTest {
|
||||
HighTierContext context = getDefaultHighTierContext();
|
||||
new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
|
||||
new CanonicalizerPhase().apply(graph, context);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, referenceGraph, "ReferenceGraph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, referenceGraph, "ReferenceGraph");
|
||||
assertEquals(referenceGraph, graph);
|
||||
} catch (Throwable e) {
|
||||
throw Debug.handle(e);
|
||||
|
@ -142,7 +142,7 @@ public class FindUniqueDefaultMethodTest extends GraalCompilerTest {
|
||||
try (Scope s = Debug.scope("InstanceOfTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) {
|
||||
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
|
||||
compile(graph.method(), graph);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet);
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, snippet);
|
||||
return graph;
|
||||
} catch (Throwable e) {
|
||||
throw Debug.handle(e);
|
||||
|
@ -82,7 +82,7 @@ public class FloatingReadTest extends GraphScheduleTest {
|
||||
}
|
||||
}
|
||||
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After lowering");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "After lowering");
|
||||
|
||||
Assert.assertNotNull(returnNode);
|
||||
Assert.assertNotNull(monitorexit);
|
||||
|
@ -78,6 +78,7 @@ import org.graalvm.compiler.nodes.FrameState;
|
||||
import org.graalvm.compiler.nodes.FullInfopointNode;
|
||||
import org.graalvm.compiler.nodes.InvokeNode;
|
||||
import org.graalvm.compiler.nodes.InvokeWithExceptionNode;
|
||||
import org.graalvm.compiler.nodes.ParameterNode;
|
||||
import org.graalvm.compiler.nodes.ProxyNode;
|
||||
import org.graalvm.compiler.nodes.ReturnNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
@ -91,6 +92,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
|
||||
import org.graalvm.compiler.nodes.java.AccessFieldNode;
|
||||
import org.graalvm.compiler.nodes.spi.LoweringProvider;
|
||||
import org.graalvm.compiler.nodes.spi.Replacements;
|
||||
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
|
||||
@ -121,6 +123,7 @@ import jdk.vm.ci.code.BailoutException;
|
||||
import jdk.vm.ci.code.CodeCacheProvider;
|
||||
import jdk.vm.ci.code.InstalledCode;
|
||||
import jdk.vm.ci.code.TargetDescription;
|
||||
import jdk.vm.ci.meta.Assumptions.Assumption;
|
||||
import jdk.vm.ci.meta.ConstantReflectionProvider;
|
||||
import jdk.vm.ci.meta.DeoptimizationReason;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
@ -130,7 +133,6 @@ import jdk.vm.ci.meta.ProfilingInfo;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
import jdk.vm.ci.meta.SpeculationLog;
|
||||
import jdk.vm.ci.meta.Assumptions.Assumption;
|
||||
import jdk.vm.ci.services.Services;
|
||||
|
||||
/**
|
||||
@ -410,13 +412,13 @@ public abstract class GraalCompilerTest extends GraalTest {
|
||||
String mismatchString = compareGraphStrings(expected, expectedString, graph, actualString);
|
||||
|
||||
if (!excludeVirtual && getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) {
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "Node count not matching - expected");
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Node count not matching - actual");
|
||||
Debug.dump(Debug.BASIC_LEVEL, expected, "Node count not matching - expected");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Node count not matching - actual");
|
||||
Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount() + "\n" + mismatchString);
|
||||
}
|
||||
if (!expectedString.equals(actualString)) {
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "mismatching graphs - expected");
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "mismatching graphs - actual");
|
||||
Debug.dump(Debug.BASIC_LEVEL, expected, "mismatching graphs - expected");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "mismatching graphs - actual");
|
||||
Assert.fail(mismatchString);
|
||||
}
|
||||
}
|
||||
@ -482,22 +484,25 @@ public abstract class GraalCompilerTest extends GraalTest {
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (Block block : scheduleResult.getCFG().getBlocks()) {
|
||||
result.append("Block " + block + " ");
|
||||
result.append("Block ").append(block).append(' ');
|
||||
if (block == scheduleResult.getCFG().getStartBlock()) {
|
||||
result.append("* ");
|
||||
}
|
||||
result.append("-> ");
|
||||
for (Block succ : block.getSuccessors()) {
|
||||
result.append(succ + " ");
|
||||
result.append(succ).append(' ');
|
||||
}
|
||||
result.append("\n");
|
||||
result.append('\n');
|
||||
for (Node node : scheduleResult.getBlockToNodesMap().get(block)) {
|
||||
if (node instanceof ValueNode && node.isAlive()) {
|
||||
if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode || node instanceof FullInfopointNode)) {
|
||||
if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode || node instanceof FullInfopointNode || node instanceof ParameterNode)) {
|
||||
if (node instanceof ConstantNode) {
|
||||
String name = checkConstants ? node.toString(Verbosity.Name) : node.getClass().getSimpleName();
|
||||
String str = name + (excludeVirtual ? "\n" : " (" + filteredUsageCount(node) + ")\n");
|
||||
constantsLines.add(str);
|
||||
if (excludeVirtual) {
|
||||
constantsLines.add(name);
|
||||
} else {
|
||||
constantsLines.add(name + " (" + filteredUsageCount(node) + ")");
|
||||
}
|
||||
} else {
|
||||
int id;
|
||||
if (canonicalId.get(node) != null) {
|
||||
@ -507,8 +512,17 @@ public abstract class GraalCompilerTest extends GraalTest {
|
||||
canonicalId.set(node, id);
|
||||
}
|
||||
String name = node.getClass().getSimpleName();
|
||||
String str = " " + id + "|" + name + (excludeVirtual ? "\n" : " (" + filteredUsageCount(node) + ")\n");
|
||||
result.append(str);
|
||||
result.append(" ").append(id).append('|').append(name);
|
||||
if (node instanceof AccessFieldNode) {
|
||||
result.append('#');
|
||||
result.append(((AccessFieldNode) node).field());
|
||||
}
|
||||
if (!excludeVirtual) {
|
||||
result.append(" (");
|
||||
result.append(filteredUsageCount(node));
|
||||
result.append(')');
|
||||
}
|
||||
result.append('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -516,14 +530,14 @@ public abstract class GraalCompilerTest extends GraalTest {
|
||||
}
|
||||
|
||||
StringBuilder constantsLinesResult = new StringBuilder();
|
||||
constantsLinesResult.append(constantsLines.size() + " constants:\n");
|
||||
constantsLinesResult.append(constantsLines.size()).append(" constants:\n");
|
||||
Collections.sort(constantsLines);
|
||||
for (String s : constantsLines) {
|
||||
constantsLinesResult.append(s);
|
||||
constantsLinesResult.append("\n");
|
||||
constantsLinesResult.append('\n');
|
||||
}
|
||||
|
||||
return constantsLines.toString() + result.toString();
|
||||
return constantsLinesResult.toString() + result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -545,15 +559,15 @@ public abstract class GraalCompilerTest extends GraalTest {
|
||||
StringBuilder result = new StringBuilder();
|
||||
Block[] blocks = scheduleResult.getCFG().getBlocks();
|
||||
for (Block block : blocks) {
|
||||
result.append("Block " + block + " ");
|
||||
result.append("Block ").append(block).append(' ');
|
||||
if (block == scheduleResult.getCFG().getStartBlock()) {
|
||||
result.append("* ");
|
||||
}
|
||||
result.append("-> ");
|
||||
for (Block succ : block.getSuccessors()) {
|
||||
result.append(succ + " ");
|
||||
result.append(succ).append(' ');
|
||||
}
|
||||
result.append("\n");
|
||||
result.append('\n');
|
||||
for (Node node : scheduleResult.getBlockToNodesMap().get(block)) {
|
||||
result.append(String.format("%1S\n", node));
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ public class IfCanonicalizerTest extends GraalCompilerTest {
|
||||
n.replaceFirstInput(param, constant);
|
||||
}
|
||||
}
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
|
||||
for (FrameState fs : param.usages().filter(FrameState.class).snapshot()) {
|
||||
fs.replaceFirstInput(param, null);
|
||||
|
@ -25,7 +25,8 @@ package org.graalvm.compiler.core.test;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.loop.DefaultLoopPolicies;
|
||||
import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
|
||||
import org.graalvm.compiler.nodes.java.MonitorExitNode;
|
||||
@ -91,6 +92,26 @@ public class LockEliminationTest extends GraalCompilerTest {
|
||||
assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
|
||||
}
|
||||
|
||||
public void testUnrolledSyncSnippet(Object a) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
synchronized (a) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnrolledSync() {
|
||||
StructuredGraph graph = getGraph("testUnrolledSyncSnippet");
|
||||
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
|
||||
canonicalizer.apply(graph, new PhaseContext(getProviders()));
|
||||
HighTierContext context = getDefaultHighTierContext();
|
||||
new LoopFullUnrollPhase(canonicalizer, new DefaultLoopPolicies()).apply(graph, context);
|
||||
new LockEliminationPhase().apply(graph);
|
||||
assertDeepEquals(1, graph.getNodes().filter(RawMonitorEnterNode.class).count());
|
||||
assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
|
||||
}
|
||||
|
||||
private StructuredGraph getGraph(String snippet) {
|
||||
ResolvedJavaMethod method = getResolvedJavaMethod(snippet);
|
||||
StructuredGraph graph = parseEager(method, AllowAssumptions.YES);
|
||||
|
@ -717,7 +717,7 @@ public class MemoryScheduleTest extends GraphScheduleTest {
|
||||
if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
|
||||
graph.clearAllStateAfter();
|
||||
}
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "after removal of framestates");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "after removal of framestates");
|
||||
|
||||
new FloatingReadPhase().apply(graph);
|
||||
new RemoveValueProxyPhase().apply(graph);
|
||||
|
@ -61,7 +61,7 @@ public class MergeCanonicalizerTest extends GraalCompilerTest {
|
||||
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
|
||||
new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
|
||||
new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
assertDeepEquals(returnCount, graph.getNodes(ReturnNode.TYPE).count());
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ public class NestedLoopTest extends GraalCompilerTest {
|
||||
|
||||
private void test(String snippet, int rootExits, int nestedExits, int innerExits) {
|
||||
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
|
||||
|
||||
Assert.assertEquals(3, cfg.getLoops().size());
|
||||
@ -162,7 +162,7 @@ public class NestedLoopTest extends GraalCompilerTest {
|
||||
Assert.assertEquals(rootExits, rootLoop.getExits().size());
|
||||
Assert.assertEquals(nestedExits, nestedLoop.getExits().size());
|
||||
Assert.assertEquals(innerExits, innerMostLoop.getExits().size());
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
}
|
||||
|
||||
private static boolean contains(Loop<Block> loop, Invoke node, ControlFlowGraph cfg) {
|
||||
|
@ -58,9 +58,11 @@ public class NodePropertiesTest extends GraalCompilerTest {
|
||||
x = 2;
|
||||
sideEffect = null;
|
||||
}
|
||||
int b = 4;
|
||||
sideEffect = null;
|
||||
int c = b % 5;
|
||||
// can shift
|
||||
return a * x * 4;
|
||||
return a * x * c;
|
||||
}
|
||||
|
||||
public static int test2Snippet(int a) {
|
||||
@ -249,7 +251,7 @@ public class NodePropertiesTest extends GraalCompilerTest {
|
||||
gc2.apply(g2, htc);
|
||||
Debug.log("Test Graph Cost --> 1.Graph cost:%f vs. 2.Graph cost:%f\n", gc1.finalCycles, gc2.finalCycles);
|
||||
Assert.assertTrue(gc2.finalCycles > gc1.finalCycles);
|
||||
Assert.assertTrue(gc2.finalSize == gc1.finalSize + 1/* mul has 3 const input */);
|
||||
Assert.assertTrue(gc2.finalSize == gc1.finalSize);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -70,7 +70,7 @@ public class PhiCreationTests extends GraalCompilerTest {
|
||||
@Test
|
||||
public void test3() {
|
||||
StructuredGraph graph = parseEager("test3Snippet", AllowAssumptions.YES);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext());
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ public class PhiCreationTests extends GraalCompilerTest {
|
||||
@Test
|
||||
public void test4() {
|
||||
StructuredGraph graph = parseEager("test4Snippet", AllowAssumptions.YES);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext());
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ public class PushThroughIfTest extends GraalCompilerTest {
|
||||
|
||||
private void test(String snippet, String reference) {
|
||||
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
for (FrameState fs : graph.getNodes(FrameState.TYPE).snapshot()) {
|
||||
fs.replaceAtUsages(null);
|
||||
GraphUtil.killWithUnusedFloatingInputs(fs);
|
||||
|
@ -94,7 +94,7 @@ public class ReadAfterCheckCastTest extends GraphScheduleTest {
|
||||
new FloatingReadPhase().apply(graph);
|
||||
canonicalizer.apply(graph, context);
|
||||
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After lowering");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "After lowering");
|
||||
|
||||
for (FloatingReadNode node : graph.getNodes(ParameterNode.TYPE).first().usages().filter(FloatingReadNode.class)) {
|
||||
// Checking that the parameter a is not directly used for the access to field
|
||||
|
@ -131,7 +131,7 @@ public class ScalarTypeSystemTest extends GraalCompilerTest {
|
||||
private void test(final String snippet, final String referenceSnippet) {
|
||||
// No debug scope to reduce console noise for @Test(expected = ...) tests
|
||||
StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
PhaseContext context = new PhaseContext(getProviders());
|
||||
new CanonicalizerPhase().apply(graph, context);
|
||||
StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO);
|
||||
|
@ -69,7 +69,7 @@ public class SchedulingTest2 extends GraphScheduleTest {
|
||||
BeginNode beginNode = graph.add(new BeginNode());
|
||||
returnNode.replaceAtPredecessor(beginNode);
|
||||
beginNode.setNext(returnNode);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST);
|
||||
schedulePhase.apply(graph);
|
||||
ScheduleResult schedule = graph.getLastSchedule();
|
||||
|
@ -41,7 +41,7 @@ import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
|
||||
public class SimpleCFGTest extends GraalCompilerTest {
|
||||
|
||||
private static void dumpGraph(final StructuredGraph graph) {
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -88,7 +88,7 @@ public class StraighteningTest extends GraalCompilerTest {
|
||||
private void test(final String snippet) {
|
||||
// No debug scope to reduce console noise for @Test(expected = ...) tests
|
||||
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
|
||||
StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES);
|
||||
assertEquals(referenceGraph, graph);
|
||||
|
@ -180,7 +180,7 @@ public class TypeSystemTest extends GraalCompilerTest {
|
||||
|
||||
private void test(String snippet, String referenceSnippet) {
|
||||
StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
/*
|
||||
* When using FlowSensitiveReductionPhase instead of ConditionalEliminationPhase,
|
||||
* tail-duplication gets activated thus resulting in a graph with more nodes than the
|
||||
@ -200,8 +200,8 @@ public class TypeSystemTest extends GraalCompilerTest {
|
||||
@Override
|
||||
protected void assertEquals(StructuredGraph expected, StructuredGraph graph) {
|
||||
if (getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) {
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "expected (node count)");
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "graph (node count)");
|
||||
Debug.dump(Debug.BASIC_LEVEL, expected, "expected (node count)");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "graph (node count)");
|
||||
Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount());
|
||||
}
|
||||
}
|
||||
@ -244,7 +244,7 @@ public class TypeSystemTest extends GraalCompilerTest {
|
||||
StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
|
||||
new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
|
||||
new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph " + snippet);
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph " + snippet);
|
||||
Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext());
|
||||
}
|
||||
}
|
||||
|
@ -83,9 +83,28 @@ public class VerifyDebugUsageTest {
|
||||
|
||||
@Override
|
||||
protected void run(StructuredGraph graph) {
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "%s", graph.toString());
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "%s", graph.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static class InvalidDumpLevelPhase extends Phase {
|
||||
|
||||
@Override
|
||||
protected void run(StructuredGraph graph) {
|
||||
Debug.dump(Debug.VERY_DETAILED_LEVEL + 1, graph, "%s", graph);
|
||||
}
|
||||
}
|
||||
|
||||
private static class NonConstantDumpLevelPhase extends Phase {
|
||||
|
||||
@Override
|
||||
protected void run(StructuredGraph graph) {
|
||||
Debug.dump(getLevel(), graph, "%s", graph);
|
||||
}
|
||||
|
||||
int getLevel() {
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
private static class InvalidVerifyUsagePhase extends Phase {
|
||||
@ -126,7 +145,7 @@ public class VerifyDebugUsageTest {
|
||||
|
||||
@Override
|
||||
protected void run(StructuredGraph graph) {
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "error " + graph);
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "error " + graph);
|
||||
}
|
||||
|
||||
}
|
||||
@ -169,7 +188,7 @@ public class VerifyDebugUsageTest {
|
||||
|
||||
@Override
|
||||
protected void run(StructuredGraph graph) {
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "%s", graph);
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "%s", graph);
|
||||
}
|
||||
|
||||
}
|
||||
@ -233,6 +252,16 @@ public class VerifyDebugUsageTest {
|
||||
testDebugUsageClass(InvalidDumpUsagePhase.class);
|
||||
}
|
||||
|
||||
@Test(expected = VerificationError.class)
|
||||
public void testDumpLevelInvalid() {
|
||||
testDebugUsageClass(InvalidDumpLevelPhase.class);
|
||||
}
|
||||
|
||||
@Test(expected = VerificationError.class)
|
||||
public void testDumpNonConstantLevelInvalid() {
|
||||
testDebugUsageClass(NonConstantDumpLevelPhase.class);
|
||||
}
|
||||
|
||||
@Test(expected = VerificationError.class)
|
||||
public void testLogInvalidConcat() {
|
||||
testDebugUsageClass(InvalidConcatLogUsagePhase.class);
|
||||
|
@ -135,6 +135,7 @@ public class PartialEscapeAnalysisTest extends EATestBase {
|
||||
}
|
||||
|
||||
public static Object[] array = new Object[]{1, 2, 3, 4, 5, "asdf", "asdf"};
|
||||
public static char[] charArray = new char[]{1, 2, 3, 4, 5, 'a', 'f'};
|
||||
|
||||
public static Object testArrayCopySnippet(int a) {
|
||||
Object[] tmp = new Object[]{a != 1 ? array[a] : null};
|
||||
@ -143,6 +144,18 @@ public class PartialEscapeAnalysisTest extends EATestBase {
|
||||
return tmp2[4];
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrimitiveArraycopy() {
|
||||
testPartialEscapeAnalysis("testPrimitiveArraycopySnippet", 0, 0);
|
||||
}
|
||||
|
||||
public static Object testPrimitiveArraycopySnippet(int a) {
|
||||
char[] tmp = new char[]{a != 1 ? charArray[a] : 0};
|
||||
char[] tmp2 = new char[5];
|
||||
System.arraycopy(tmp, 0, tmp2, 4, 1);
|
||||
return tmp2[4];
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testCache() {
|
||||
|
@ -244,10 +244,10 @@ public class InliningTest extends GraalCompilerTest {
|
||||
? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true))
|
||||
: getDefaultGraphBuilderSuite();
|
||||
HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
new CanonicalizerPhase().apply(graph, context);
|
||||
new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
|
||||
new CanonicalizerPhase().apply(graph, context);
|
||||
new DeadCodeEliminationPhase().apply(graph);
|
||||
return graph;
|
||||
|
@ -121,7 +121,7 @@ public class NestedLoopEffectsPhaseComplexityTest extends GraalCompilerTest {
|
||||
long start = System.currentTimeMillis();
|
||||
phase.apply(g, context);
|
||||
long end = System.currentTimeMillis();
|
||||
Debug.dump(Debug.DETAILED_LOG_LEVEL, g, "After %s", phase.contractorName());
|
||||
Debug.dump(Debug.DETAILED_LEVEL, g, "After %s", phase.contractorName());
|
||||
return end - start;
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ public class NestedLoopEffectsPhaseComplexityTest extends GraalCompilerTest {
|
||||
next = callerGraph.getNodes(MethodCallTargetNode.TYPE).first().invoke();
|
||||
EconomicSet<Node> canonicalizeNodes = InliningUtil.inlineForCanonicalization(next, calleeGraph, false, calleeMethod);
|
||||
canonicalizer.applyIncremental(callerGraph, context, canonicalizeNodes);
|
||||
Debug.dump(Debug.DETAILED_LOG_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i);
|
||||
Debug.dump(Debug.DETAILED_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i);
|
||||
}
|
||||
return callerGraph;
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ package org.graalvm.compiler.core.test.tutorial;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.graalvm.compiler.bytecode.Bytecode;
|
||||
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
|
||||
import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
|
||||
@ -56,7 +58,11 @@ public class GraalTutorial extends InvokeGraal {
|
||||
byte[] bytecodes = bytecode.getCode();
|
||||
Assert.assertNotNull(bytecodes);
|
||||
|
||||
System.out.println(new BytecodeDisassembler().disassemble(bytecode));
|
||||
Pattern disassemblyLineRE = Pattern.compile(" *\\d+: [a-z][\\w_]+");
|
||||
String disassembly = new BytecodeDisassembler().disassemble(bytecode);
|
||||
for (String line : disassembly.split("\\n")) {
|
||||
Assert.assertTrue(line, disassemblyLineRE.matcher(line).find());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -39,6 +39,7 @@ import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugCounter;
|
||||
import org.graalvm.compiler.debug.DebugTimer;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.debug.MethodFilter;
|
||||
import org.graalvm.compiler.debug.internal.method.MethodMetricsRootScopeInfo;
|
||||
import org.graalvm.compiler.lir.LIR;
|
||||
import org.graalvm.compiler.lir.alloc.OutOfRegistersException;
|
||||
@ -175,10 +176,42 @@ public class GraalCompiler {
|
||||
} catch (Throwable e) {
|
||||
throw Debug.handle(e);
|
||||
}
|
||||
checkForRequestedCrash(r.graph);
|
||||
return r.compilationResult;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the {@link GraalCompilerOptions#CrashAt} option indicates that the compilation
|
||||
* of {@code graph} should result in an exception.
|
||||
*
|
||||
* @param graph a graph currently being compiled
|
||||
* @throws RuntimeException if the value of {@link GraalCompilerOptions#CrashAt} matches
|
||||
* {@code graph.method()} or {@code graph.name}
|
||||
*/
|
||||
private static void checkForRequestedCrash(StructuredGraph graph) {
|
||||
String methodPattern = GraalCompilerOptions.CrashAt.getValue(graph.getOptions());
|
||||
if (methodPattern != null) {
|
||||
String crashLabel = null;
|
||||
ResolvedJavaMethod method = graph.method();
|
||||
if (method == null) {
|
||||
if (graph.name.contains(methodPattern)) {
|
||||
crashLabel = graph.name;
|
||||
}
|
||||
} else {
|
||||
MethodFilter[] filters = MethodFilter.parse(methodPattern);
|
||||
for (MethodFilter filter : filters) {
|
||||
if (filter.matches(method)) {
|
||||
crashLabel = method.format("%H.%n(%p)");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (crashLabel != null) {
|
||||
throw new RuntimeException("Forced crash after compiling " + crashLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the graph, optimizes it.
|
||||
*/
|
||||
@ -190,21 +223,25 @@ public class GraalCompiler {
|
||||
if (graph.start().next() == null) {
|
||||
graphBuilderSuite.apply(graph, highTierContext);
|
||||
new DeadCodeEliminationPhase(DeadCodeEliminationPhase.Optionality.Optional).apply(graph);
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "After parsing");
|
||||
} else {
|
||||
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "initial state");
|
||||
Debug.dump(Debug.INFO_LEVEL, graph, "initial state");
|
||||
}
|
||||
|
||||
suites.getHighTier().apply(graph, highTierContext);
|
||||
graph.maybeCompress();
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "After high tier");
|
||||
|
||||
MidTierContext midTierContext = new MidTierContext(providers, target, optimisticOpts, profilingInfo);
|
||||
suites.getMidTier().apply(graph, midTierContext);
|
||||
graph.maybeCompress();
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "After mid tier");
|
||||
|
||||
LowTierContext lowTierContext = new LowTierContext(providers, target);
|
||||
suites.getLowTier().apply(graph, lowTierContext);
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "After low tier");
|
||||
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph.getLastSchedule(), "Final HIR schedule");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph.getLastSchedule(), "Final HIR schedule");
|
||||
} catch (Throwable e) {
|
||||
throw Debug.handle(e);
|
||||
} finally {
|
||||
@ -269,7 +306,7 @@ public class GraalCompiler {
|
||||
linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock);
|
||||
|
||||
lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions());
|
||||
Debug.dump(Debug.INFO_LOG_LEVEL, lir, "After linear scan order");
|
||||
Debug.dump(Debug.INFO_LEVEL, lir, "After linear scan order");
|
||||
} catch (Throwable e) {
|
||||
throw Debug.handle(e);
|
||||
}
|
||||
@ -283,9 +320,9 @@ public class GraalCompiler {
|
||||
new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context);
|
||||
|
||||
try (Scope s = Debug.scope("LIRStages", nodeLirGen, lir)) {
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, lir, "After LIR generation");
|
||||
Debug.dump(Debug.BASIC_LEVEL, lir, "After LIR generation");
|
||||
LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo));
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, lir, "Before code generation");
|
||||
Debug.dump(Debug.BASIC_LEVEL, lir, "Before code generation");
|
||||
return result;
|
||||
} catch (Throwable e) {
|
||||
throw Debug.handle(e);
|
||||
@ -365,7 +402,7 @@ public class GraalCompiler {
|
||||
Debug.counter("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size());
|
||||
}
|
||||
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, compilationResult, "After code generation");
|
||||
Debug.dump(Debug.BASIC_LEVEL, compilationResult, "After code generation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,8 @@ public class GraalCompilerOptions {
|
||||
public static final OptionKey<Boolean> ExitVMOnException = new OptionKey<>(false);
|
||||
@Option(help = "", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> PrintStackTraceOnException = new OptionKey<>(false);
|
||||
@Option(help = "Pattern (see MethodFilter for format) for method that will trigger an exception when compiled. " +
|
||||
"This option exists to test handling compilation crashes gracefully.", type = OptionType.Debug)
|
||||
public static final OptionKey<String> CrashAt = new OptionKey<>(null);
|
||||
// @formatter:on
|
||||
|
||||
}
|
||||
|
@ -91,12 +91,12 @@ public class GraphChangeMonitoringPhase<C extends PhaseContext> extends PhaseSui
|
||||
listener = new HashSetNodeEventListener();
|
||||
try (NodeEventScope s = graph.trackNodeEvents(listener)) {
|
||||
try (Scope s2 = Debug.scope("WithGraphChangeMonitoring")) {
|
||||
if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) {
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "*** Before phase %s", getName());
|
||||
if (Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) {
|
||||
Debug.dump(Debug.DETAILED_LEVEL, graph, "*** Before phase %s", getName());
|
||||
}
|
||||
super.run(graph, context);
|
||||
if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) {
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "*** After phase %s %s", getName(), filteredNodes);
|
||||
if (Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) {
|
||||
Debug.dump(Debug.DETAILED_LEVEL, graph, "*** After phase %s %s", getName(), filteredNodes);
|
||||
}
|
||||
Debug.log("*** %s %s %s\n", message, graph, filteredNodes);
|
||||
}
|
||||
|
@ -122,11 +122,41 @@ public class Debug {
|
||||
return config.isDumpEnabledForMethod();
|
||||
}
|
||||
|
||||
public static final int BASIC_LOG_LEVEL = 1;
|
||||
public static final int INFO_LOG_LEVEL = 2;
|
||||
public static final int VERBOSE_LOG_LEVEL = 3;
|
||||
public static final int DETAILED_LOG_LEVEL = 4;
|
||||
public static final int VERY_DETAILED_LOG_LEVEL = 5;
|
||||
/**
|
||||
* Basic debug level.
|
||||
*
|
||||
* For HIR dumping, only ~5 graphs per method: after parsing, after inlining, after high tier,
|
||||
* after mid tier, after low tier.
|
||||
*/
|
||||
public static final int BASIC_LEVEL = 1;
|
||||
|
||||
/**
|
||||
* Informational debug level.
|
||||
*
|
||||
* HIR dumping: One graph after each applied top-level phase.
|
||||
*/
|
||||
public static final int INFO_LEVEL = 2;
|
||||
|
||||
/**
|
||||
* Verbose debug level.
|
||||
*
|
||||
* HIR dumping: One graph after each phase (including sub phases).
|
||||
*/
|
||||
public static final int VERBOSE_LEVEL = 3;
|
||||
|
||||
/**
|
||||
* Detailed debug level.
|
||||
*
|
||||
* HIR dumping: Graphs within phases where interesting for a phase, max ~5 per phase.
|
||||
*/
|
||||
public static final int DETAILED_LEVEL = 4;
|
||||
|
||||
/**
|
||||
* Very detailed debug level.
|
||||
*
|
||||
* HIR dumping: Graphs per node granularity graph change (before/after change).
|
||||
*/
|
||||
public static final int VERY_DETAILED_LEVEL = 5;
|
||||
|
||||
public static boolean isDumpEnabled(int dumpLevel) {
|
||||
return ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel);
|
||||
@ -183,7 +213,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static boolean isLogEnabled() {
|
||||
return isLogEnabled(BASIC_LOG_LEVEL);
|
||||
return isLogEnabled(BASIC_LEVEL);
|
||||
}
|
||||
|
||||
public static boolean isLogEnabled(int logLevel) {
|
||||
@ -420,7 +450,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String msg) {
|
||||
log(BASIC_LOG_LEVEL, msg);
|
||||
log(BASIC_LEVEL, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -435,7 +465,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String format, Object arg) {
|
||||
log(BASIC_LOG_LEVEL, format, arg);
|
||||
log(BASIC_LEVEL, format, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -451,7 +481,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String format, int arg) {
|
||||
log(BASIC_LOG_LEVEL, format, arg);
|
||||
log(BASIC_LEVEL, format, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -467,7 +497,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String format, Object arg1, Object arg2) {
|
||||
log(BASIC_LOG_LEVEL, format, arg1, arg2);
|
||||
log(BASIC_LEVEL, format, arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -480,7 +510,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String format, int arg1, Object arg2) {
|
||||
log(BASIC_LOG_LEVEL, format, arg1, arg2);
|
||||
log(BASIC_LEVEL, format, arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -493,7 +523,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String format, Object arg1, int arg2) {
|
||||
log(BASIC_LOG_LEVEL, format, arg1, arg2);
|
||||
log(BASIC_LEVEL, format, arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -506,7 +536,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String format, int arg1, int arg2) {
|
||||
log(BASIC_LOG_LEVEL, format, arg1, arg2);
|
||||
log(BASIC_LEVEL, format, arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -519,7 +549,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String format, Object arg1, Object arg2, Object arg3) {
|
||||
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3);
|
||||
log(BASIC_LEVEL, format, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -532,7 +562,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String format, int arg1, int arg2, int arg3) {
|
||||
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3);
|
||||
log(BASIC_LEVEL, format, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -545,7 +575,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4) {
|
||||
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4);
|
||||
log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -558,7 +588,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
|
||||
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5);
|
||||
log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -571,7 +601,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) {
|
||||
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -584,11 +614,11 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) {
|
||||
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
|
||||
log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
|
||||
}
|
||||
|
||||
public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) {
|
||||
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
||||
log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -607,7 +637,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) {
|
||||
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
|
||||
log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
|
||||
}
|
||||
|
||||
public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) {
|
||||
@ -617,7 +647,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) {
|
||||
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
|
||||
log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
|
||||
}
|
||||
|
||||
public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) {
|
||||
@ -627,7 +657,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static void logv(String format, Object... args) {
|
||||
logv(BASIC_LOG_LEVEL, format, args);
|
||||
logv(BASIC_LEVEL, format, args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -655,7 +685,7 @@ public class Debug {
|
||||
@Deprecated
|
||||
public static void log(String format, Object[] args) {
|
||||
assert false : "shouldn't use this";
|
||||
log(BASIC_LOG_LEVEL, format, args);
|
||||
log(BASIC_LEVEL, format, args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -670,6 +700,14 @@ public class Debug {
|
||||
logv(logLevel, format, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces an unconditional dump. This method exists mainly for debugging. It can also be used to
|
||||
* force a graph dump from IDEs that support invoking a Java method while at a breakpoint.
|
||||
*/
|
||||
public static void forceDump(Object object, String format, Object... args) {
|
||||
DebugScope.forceDump(object, format, args);
|
||||
}
|
||||
|
||||
public static void dump(int dumpLevel, Object object, String msg) {
|
||||
if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) {
|
||||
DebugScope.getInstance().dump(dumpLevel, object, msg);
|
||||
@ -771,7 +809,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static Indent logAndIndent(String msg) {
|
||||
return logAndIndent(BASIC_LOG_LEVEL, msg);
|
||||
return logAndIndent(BASIC_LEVEL, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -789,7 +827,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static Indent logAndIndent(String format, Object arg) {
|
||||
return logAndIndent(BASIC_LOG_LEVEL, format, arg);
|
||||
return logAndIndent(BASIC_LEVEL, format, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -808,7 +846,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static Indent logAndIndent(String format, int arg) {
|
||||
return logAndIndent(BASIC_LOG_LEVEL, format, arg);
|
||||
return logAndIndent(BASIC_LEVEL, format, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -827,7 +865,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static Indent logAndIndent(String format, int arg1, Object arg2) {
|
||||
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2);
|
||||
return logAndIndent(BASIC_LEVEL, format, arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -841,7 +879,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static Indent logAndIndent(String format, Object arg1, int arg2) {
|
||||
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2);
|
||||
return logAndIndent(BASIC_LEVEL, format, arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -855,7 +893,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static Indent logAndIndent(String format, int arg1, int arg2) {
|
||||
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2);
|
||||
return logAndIndent(BASIC_LEVEL, format, arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -869,7 +907,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static Indent logAndIndent(String format, Object arg1, Object arg2) {
|
||||
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2);
|
||||
return logAndIndent(BASIC_LEVEL, format, arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -883,7 +921,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3) {
|
||||
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3);
|
||||
return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -897,7 +935,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static Indent logAndIndent(String format, int arg1, int arg2, int arg3) {
|
||||
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3);
|
||||
return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -911,7 +949,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static Indent logAndIndent(String format, Object arg1, int arg2, int arg3) {
|
||||
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3);
|
||||
return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -925,7 +963,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4) {
|
||||
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4);
|
||||
return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -939,7 +977,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
|
||||
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5);
|
||||
return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -953,7 +991,7 @@ public class Debug {
|
||||
}
|
||||
|
||||
public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) {
|
||||
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1001,7 +1039,7 @@ public class Debug {
|
||||
@Deprecated
|
||||
public static void logAndIndent(String format, Object[] args) {
|
||||
assert false : "shouldn't use this";
|
||||
logAndIndent(BASIC_LOG_LEVEL, format, args);
|
||||
logAndIndent(BASIC_LEVEL, format, args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,28 +41,28 @@ import org.graalvm.compiler.debug.internal.DebugScope;
|
||||
* A filter is a list of comma-separated terms of the form {@code <pattern>[:<level>]}. {@code
|
||||
* <pattern>} is interpreted as a glob pattern if it contains a "*" or "?" character. Otherwise, it
|
||||
* is interpreted as a substring. If {@code <pattern>} is empty, it matches every scope. If {@code :
|
||||
* <level>} is omitted, it defaults to {@link Debug#BASIC_LOG_LEVEL}. The term {@code ~<pattern>} is
|
||||
* a shorthand for {@code <pattern>:0} to disable a debug facility for a pattern.
|
||||
* <level>} is omitted, it defaults to {@link Debug#BASIC_LEVEL}. The term {@code ~<pattern>} is a
|
||||
* shorthand for {@code <pattern>:0} to disable a debug facility for a pattern.
|
||||
* <p>
|
||||
* The resulting log level of a scope is determined by the <em>last</em> matching term. If no term
|
||||
* matches, the log level is 0 (disabled). A filter with no terms matches every scope with a log
|
||||
* level of {@link Debug#BASIC_LOG_LEVEL}.
|
||||
* level of {@link Debug#BASIC_LEVEL}.
|
||||
*
|
||||
* <h2>Examples of filters</h2>
|
||||
*
|
||||
* <ul>
|
||||
* <li>(empty string)<br>
|
||||
* Matches any scope with log level {@link Debug#BASIC_LOG_LEVEL}.
|
||||
* Matches any scope with log level {@link Debug#BASIC_LEVEL}.
|
||||
*
|
||||
* <li>{@code :1}<br>
|
||||
* Matches any scope with log level 1.
|
||||
*
|
||||
* <li>{@code *}<br>
|
||||
* Matches any scope with log level {@link Debug#BASIC_LOG_LEVEL}.
|
||||
* Matches any scope with log level {@link Debug#BASIC_LEVEL}.
|
||||
*
|
||||
* <li>{@code CodeGen,CodeInstall}<br>
|
||||
* Matches scopes containing "CodeGen" or "CodeInstall", both with log level
|
||||
* {@link Debug#BASIC_LOG_LEVEL}.
|
||||
* {@link Debug#BASIC_LEVEL}.
|
||||
*
|
||||
* <li>{@code CodeGen:2,CodeInstall:1}<br>
|
||||
* Matches scopes containing "CodeGen" with log level 2, or "CodeInstall" with log level 1.
|
||||
@ -74,10 +74,10 @@ import org.graalvm.compiler.debug.internal.DebugScope;
|
||||
* Matches all scopes with log level 1, except those containing "Dead".
|
||||
*
|
||||
* <li>{@code Code*}<br>
|
||||
* Matches scopes starting with "Code" with log level {@link Debug#BASIC_LOG_LEVEL}.
|
||||
* Matches scopes starting with "Code" with log level {@link Debug#BASIC_LEVEL}.
|
||||
*
|
||||
* <li>{@code Code,~Dead}<br>
|
||||
* Matches scopes containing "Code" but not "Dead", with log level {@link Debug#BASIC_LOG_LEVEL}.
|
||||
* Matches scopes containing "Code" but not "Dead", with log level {@link Debug#BASIC_LEVEL}.
|
||||
* </ul>
|
||||
*/
|
||||
final class DebugFilter {
|
||||
@ -108,7 +108,7 @@ final class DebugFilter {
|
||||
level = 0;
|
||||
} else {
|
||||
pattern = t;
|
||||
level = Debug.BASIC_LOG_LEVEL;
|
||||
level = Debug.BASIC_LEVEL;
|
||||
}
|
||||
} else {
|
||||
pattern = t.substring(0, idx);
|
||||
@ -119,13 +119,13 @@ final class DebugFilter {
|
||||
} catch (NumberFormatException e) {
|
||||
switch (levelString) {
|
||||
case "basic":
|
||||
level = Debug.BASIC_LOG_LEVEL;
|
||||
level = Debug.BASIC_LEVEL;
|
||||
break;
|
||||
case "info":
|
||||
level = Debug.INFO_LOG_LEVEL;
|
||||
level = Debug.INFO_LEVEL;
|
||||
break;
|
||||
case "verbose":
|
||||
level = Debug.VERBOSE_LOG_LEVEL;
|
||||
level = Debug.VERBOSE_LEVEL;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown dump level: \"" + levelString + "\" expected basic, info, verbose or an integer");
|
||||
@ -133,7 +133,7 @@ final class DebugFilter {
|
||||
}
|
||||
|
||||
} else {
|
||||
level = Debug.BASIC_LOG_LEVEL;
|
||||
level = Debug.BASIC_LEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,7 +147,7 @@ final class DebugFilter {
|
||||
*/
|
||||
public int matchLevel(String input) {
|
||||
if (terms == null) {
|
||||
return Debug.BASIC_LOG_LEVEL;
|
||||
return Debug.BASIC_LEVEL;
|
||||
} else {
|
||||
int level = 0;
|
||||
for (Term t : terms) {
|
||||
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.debug;
|
||||
|
||||
import org.graalvm.compiler.debug.Debug.Scope;
|
||||
|
||||
/**
|
||||
* A mechanism for re-executing a task upon failure.
|
||||
*/
|
||||
public abstract class DebugRetryableTask<T> extends DelegatingDebugConfig {
|
||||
|
||||
/**
|
||||
* Calls {@link #run} on this task and if it results in an exception, calls
|
||||
* {@link #onRetry(Throwable)} and if that returns {@code true}, calls {@link #run}.
|
||||
*/
|
||||
@SuppressWarnings("try")
|
||||
public final T execute() {
|
||||
try {
|
||||
return run(null);
|
||||
} catch (Throwable t) {
|
||||
if (onRetry(t)) {
|
||||
try (Scope d = Debug.sandbox("Retrying: " + this, this)) {
|
||||
return run(t);
|
||||
} catch (Throwable t2) {
|
||||
throw Debug.handle(t2);
|
||||
}
|
||||
} else {
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs this task.
|
||||
*
|
||||
* @param failure the cause of the first execution to fail or {@code null} if this is the first
|
||||
* execution of {@link #run(Throwable)}
|
||||
*/
|
||||
protected abstract T run(Throwable failure);
|
||||
|
||||
/**
|
||||
* Notifies this object that the initial execution failed with exception {@code t} and is about
|
||||
* to be re-executed. The re-execution will use this object as the active {@link DebugConfig}.
|
||||
* As such, this method can be overridden to enable more detailed debug facilities.
|
||||
*
|
||||
* @param t an exception that terminated the first execution of this task
|
||||
* @return whether this task should be re-executed. If false, {@code t} will be re-thrown.
|
||||
*/
|
||||
protected boolean onRetry(Throwable t) {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -79,7 +79,9 @@ public class GraalDebugConfig implements DebugConfig {
|
||||
@Option(help = "Write debug values into a file instead of the terminal. " +
|
||||
"If DebugValueSummary is Thread, the thread name will be prepended.", type = OptionType.Debug)
|
||||
public static final OptionKey<String> DebugValueFile = new OptionKey<>(null);
|
||||
@Option(help = "Send Graal compiler IR to dump handlers on error", type = OptionType.Debug)
|
||||
@Option(help = "Enable debug output for stub code generation and snippet preparation.", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> DebugStubsAndSnippets = new OptionKey<>(false);
|
||||
@Option(help = "Send Graal compiler IR to dump handlers on error.", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> DumpOnError = new OptionKey<>(false);
|
||||
@Option(help = "Intercept also bailout exceptions", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> InterceptBailout = new OptionKey<>(false);
|
||||
@ -406,7 +408,7 @@ public class GraalDebugConfig implements DebugConfig {
|
||||
if (e instanceof BailoutException && !Options.InterceptBailout.getValue(options)) {
|
||||
return null;
|
||||
}
|
||||
Debug.setConfig(Debug.fixedConfig(options, Debug.BASIC_LOG_LEVEL, Debug.BASIC_LOG_LEVEL, false, false, false, false, false, dumpHandlers, verifyHandlers, output));
|
||||
Debug.setConfig(Debug.fixedConfig(options, Debug.BASIC_LEVEL, Debug.BASIC_LEVEL, false, false, false, false, false, dumpHandlers, verifyHandlers, output));
|
||||
Debug.log("Exception occurred in scope: %s", Debug.currentScope());
|
||||
Map<Object, Object> firstSeen = new IdentityHashMap<>();
|
||||
for (Object o : Debug.context()) {
|
||||
@ -414,7 +416,7 @@ public class GraalDebugConfig implements DebugConfig {
|
||||
if (!firstSeen.containsKey(o)) {
|
||||
firstSeen.put(o, o);
|
||||
if (Options.DumpOnError.getValue(options) || Options.Dump.getValue(options) != null) {
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, o, "Exception: %s", e);
|
||||
Debug.dump(Debug.BASIC_LEVEL, o, "Exception: %s", e);
|
||||
} else {
|
||||
Debug.log("Context obj %s", o);
|
||||
}
|
||||
|
@ -352,7 +352,7 @@ public final class DebugScope implements Debug.Scope {
|
||||
dumpHandler.dump(object, message);
|
||||
}
|
||||
} else {
|
||||
TTY.println("Forced dump ignored because debugging is disabled - use -Dgraal.Dump=xxx");
|
||||
TTY.println("Forced dump ignored because debugging is disabled - use -Dgraal.ForceDebugEnable=true");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,6 +405,13 @@ public class Graph {
|
||||
return add(node);
|
||||
}
|
||||
|
||||
public <T extends Node> T maybeAddOrUnique(T node) {
|
||||
if (node.isAlive()) {
|
||||
return node;
|
||||
}
|
||||
return addOrUnique(node);
|
||||
}
|
||||
|
||||
public <T extends Node> T addOrUniqueWithInputs(T node) {
|
||||
if (node.isAlive()) {
|
||||
assert node.graph() == this;
|
||||
|
@ -40,6 +40,8 @@ import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.graalvm.compiler.core.common.Fields;
|
||||
import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.Fingerprint;
|
||||
import org.graalvm.compiler.graph.Graph.NodeEvent;
|
||||
@ -131,7 +133,9 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
* Denotes an injected parameter in a {@linkplain NodeIntrinsic node intrinsic} constructor. If
|
||||
* the constructor is called as part of node intrinsification, the node intrinsifier will inject
|
||||
* an argument for the annotated parameter. Injected parameters must precede all non-injected
|
||||
* parameters in a constructor.
|
||||
* parameters in a constructor. If the type of the annotated parameter is {@link Stamp}, the
|
||||
* {@linkplain Stamp#javaType type} of the injected stamp is the return type of the annotated
|
||||
* method (which cannot be {@code void}).
|
||||
*/
|
||||
@java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
|
||||
@java.lang.annotation.Target(ElementType.PARAMETER)
|
||||
@ -140,40 +144,45 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
|
||||
/**
|
||||
* Annotates a method that can be replaced by a compiler intrinsic. A (resolved) call to the
|
||||
* annotated method can be replaced with an instance of the node class denoted by
|
||||
* {@link #value()}. For this reason, the signature of the annotated method must match the
|
||||
* signature (excluding a prefix of {@linkplain InjectedNodeParameter injected} parameters) of a
|
||||
* constructor in the node class.
|
||||
* annotated method will be processed by a generated {@code InvocationPlugin} that calls either
|
||||
* a factory method or a constructor corresponding with the annotated method.
|
||||
* <p>
|
||||
* If the node class has a static method {@code intrinsify} with a matching signature plus a
|
||||
* {@code GraphBuilderContext} as first argument, this method is called instead of creating the
|
||||
* node.
|
||||
* A factory method corresponding to an annotated method is a static method named
|
||||
* {@code intrinsify} defined in the class denoted by {@link #value()}. In order, its signature
|
||||
* is as follows:
|
||||
* <ol>
|
||||
* <li>A {@code GraphBuilderContext} parameter.</li>
|
||||
* <li>A {@code ResolvedJavaMethod} parameter.</li>
|
||||
* <li>A sequence of zero or more {@linkplain InjectedNodeParameter injected} parameters.</li>
|
||||
* <li>Remaining parameters that match the declared parameters of the annotated method.</li>
|
||||
* </ol>
|
||||
* A constructor corresponding to an annotated method is defined in the class denoted by
|
||||
* {@link #value()}. In order, its signature is as follows:
|
||||
* <ol>
|
||||
* <li>A sequence of zero or more {@linkplain InjectedNodeParameter injected} parameters.</li>
|
||||
* <li>Remaining parameters that match the declared parameters of the annotated method.</li>
|
||||
* </ol>
|
||||
* There must be exactly one such factory method or constructor corresponding to a
|
||||
* {@link NodeIntrinsic} annotated method.
|
||||
*/
|
||||
@java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
|
||||
@java.lang.annotation.Target(ElementType.METHOD)
|
||||
public static @interface NodeIntrinsic {
|
||||
|
||||
/**
|
||||
* Gets the {@link Node} subclass instantiated when intrinsifying a call to the annotated
|
||||
* method. If not specified, then the class in which the annotated method is declared is
|
||||
* used (and is assumed to be a {@link Node} subclass).
|
||||
* The class declaring the factory method or {@link Node} subclass declaring the constructor
|
||||
* used to intrinsify a call to the annotated method. The default value is the class in
|
||||
* which the annotated method is declared.
|
||||
*/
|
||||
Class<?> value() default NodeIntrinsic.class;
|
||||
|
||||
/**
|
||||
* Determines if the stamp of the instantiated intrinsic node has its stamp set from the
|
||||
* return type of the annotated method.
|
||||
* <p>
|
||||
* When it is set to true, the stamp that is passed in to the constructor of ValueNode is
|
||||
* ignored and can therefore safely be {@code null}.
|
||||
* If {@code true}, the factory method or constructor selected by the annotation must have
|
||||
* an {@linkplain InjectedNodeParameter injected} {@link Stamp} parameter. Calling
|
||||
* {@link AbstractPointerStamp#nonNull()} on the injected stamp is guaranteed to return
|
||||
* {@code true}.
|
||||
*/
|
||||
boolean setStampFromReturnType() default false;
|
||||
|
||||
/**
|
||||
* Determines if the stamp of the instantiated intrinsic node is guaranteed to be non-null.
|
||||
* Generally used in conjunction with {@link #setStampFromReturnType()}.
|
||||
*/
|
||||
boolean returnStampIsNonNull() default false;
|
||||
boolean injectedStampIsNonNull() default false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -304,7 +313,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
* @return an {@link NodeIterable iterable} for all non-null successor edges.
|
||||
*/
|
||||
public NodeIterable<Node> successors() {
|
||||
assert !this.isDeleted();
|
||||
assert !this.isDeleted() : this;
|
||||
return nodeClass.getSuccessorIterable(this);
|
||||
}
|
||||
|
||||
@ -328,7 +337,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
if (usage1 == null) {
|
||||
return 1;
|
||||
}
|
||||
return 2 + extraUsagesCount;
|
||||
return INLINE_USAGE_COUNT + extraUsagesCount;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -391,30 +400,45 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
}
|
||||
|
||||
private void movUsageFromEndTo(int destIndex) {
|
||||
int lastIndex = this.getUsageCount() - 1;
|
||||
if (destIndex == 0) {
|
||||
if (lastIndex == 0) {
|
||||
usage0 = null;
|
||||
return;
|
||||
} else if (lastIndex == 1) {
|
||||
if (destIndex >= INLINE_USAGE_COUNT) {
|
||||
movUsageFromEndToExtraUsages(destIndex - INLINE_USAGE_COUNT);
|
||||
} else if (destIndex == 1) {
|
||||
movUsageFromEndToIndexOne();
|
||||
} else {
|
||||
assert destIndex == 0;
|
||||
movUsageFromEndToIndexZero();
|
||||
}
|
||||
}
|
||||
|
||||
private void movUsageFromEndToExtraUsages(int destExtraIndex) {
|
||||
this.extraUsagesCount--;
|
||||
Node n = extraUsages[extraUsagesCount];
|
||||
extraUsages[destExtraIndex] = n;
|
||||
extraUsages[extraUsagesCount] = null;
|
||||
}
|
||||
|
||||
private void movUsageFromEndToIndexZero() {
|
||||
if (extraUsagesCount > 0) {
|
||||
this.extraUsagesCount--;
|
||||
usage0 = extraUsages[extraUsagesCount];
|
||||
extraUsages[extraUsagesCount] = null;
|
||||
} else if (usage1 != null) {
|
||||
usage0 = usage1;
|
||||
usage1 = null;
|
||||
return;
|
||||
} else {
|
||||
usage0 = extraUsages[lastIndex - INLINE_USAGE_COUNT];
|
||||
usage0 = null;
|
||||
}
|
||||
} else if (destIndex == 1) {
|
||||
if (lastIndex == 1) {
|
||||
usage1 = null;
|
||||
return;
|
||||
}
|
||||
usage1 = extraUsages[lastIndex - INLINE_USAGE_COUNT];
|
||||
} else {
|
||||
Node n = extraUsages[lastIndex - INLINE_USAGE_COUNT];
|
||||
extraUsages[destIndex - INLINE_USAGE_COUNT] = n;
|
||||
}
|
||||
extraUsages[lastIndex - INLINE_USAGE_COUNT] = null;
|
||||
|
||||
private void movUsageFromEndToIndexOne() {
|
||||
if (extraUsagesCount > 0) {
|
||||
this.extraUsagesCount--;
|
||||
usage1 = extraUsages[extraUsagesCount];
|
||||
extraUsages[extraUsagesCount] = null;
|
||||
} else {
|
||||
assert usage1 != null;
|
||||
usage1 = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -425,20 +449,21 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
*/
|
||||
public boolean removeUsage(Node node) {
|
||||
assert node != null;
|
||||
// It is critical that this method maintains the invariant that
|
||||
// the usage list has no null element preceding a non-null element
|
||||
// For large graphs, usage removal is performance critical.
|
||||
// Furthermore, it is critical that this method maintains the invariant that the usage list
|
||||
// has no null element preceding a non-null element.
|
||||
incUsageModCount();
|
||||
if (usage0 == node) {
|
||||
this.movUsageFromEndTo(0);
|
||||
movUsageFromEndToIndexZero();
|
||||
return true;
|
||||
}
|
||||
if (usage1 == node) {
|
||||
this.movUsageFromEndTo(1);
|
||||
movUsageFromEndToIndexOne();
|
||||
return true;
|
||||
}
|
||||
for (int i = this.extraUsagesCount - 1; i >= 0; i--) {
|
||||
if (extraUsages[i] == node) {
|
||||
this.movUsageFromEndTo(i + INLINE_USAGE_COUNT);
|
||||
movUsageFromEndToExtraUsages(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -537,8 +562,9 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
assert assertTrue(id == INITIAL_ID, "unexpected id: %d", id);
|
||||
this.graph = newGraph;
|
||||
newGraph.register(this);
|
||||
this.getNodeClass().registerAtInputsAsUsage(this);
|
||||
this.getNodeClass().registerAtSuccessorsAsPredecessor(this);
|
||||
NodeClass<? extends Node> nc = nodeClass;
|
||||
nc.registerAtInputsAsUsage(this);
|
||||
nc.registerAtSuccessorsAsPredecessor(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -588,7 +614,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
}
|
||||
|
||||
public final void replaceAtUsages(Node other) {
|
||||
replaceAtUsages(other, null, null);
|
||||
replaceAtAllUsages(other, (Node) null);
|
||||
}
|
||||
|
||||
public final void replaceAtUsages(Node other, Predicate<Node> filter) {
|
||||
@ -606,11 +632,39 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
}
|
||||
|
||||
protected void replaceAtUsages(Node other, Predicate<Node> filter, Node toBeDeleted) {
|
||||
if (filter == null) {
|
||||
replaceAtAllUsages(other, toBeDeleted);
|
||||
} else {
|
||||
replaceAtMatchingUsages(other, filter, toBeDeleted);
|
||||
}
|
||||
}
|
||||
|
||||
protected void replaceAtAllUsages(Node other, Node toBeDeleted) {
|
||||
assert checkReplaceWith(other);
|
||||
int i = 0;
|
||||
while (i < this.getUsageCount()) {
|
||||
Node usage = this.getUsageAt(i);
|
||||
if (filter == null || filter.test(usage)) {
|
||||
if (usage0 == null) {
|
||||
return;
|
||||
}
|
||||
replaceAtUsage(other, toBeDeleted, usage0);
|
||||
usage0 = null;
|
||||
|
||||
if (usage1 == null) {
|
||||
return;
|
||||
}
|
||||
replaceAtUsage(other, toBeDeleted, usage1);
|
||||
usage1 = null;
|
||||
|
||||
if (extraUsagesCount <= 0) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < extraUsagesCount; i++) {
|
||||
Node usage = extraUsages[i];
|
||||
replaceAtUsage(other, toBeDeleted, usage);
|
||||
}
|
||||
this.extraUsages = NO_NODES;
|
||||
this.extraUsagesCount = 0;
|
||||
}
|
||||
|
||||
private void replaceAtUsage(Node other, Node toBeDeleted, Node usage) {
|
||||
boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other);
|
||||
assert assertTrue(result, "not found in inputs, usage: %s", usage);
|
||||
/*
|
||||
@ -622,6 +676,16 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
if (other != null) {
|
||||
other.addUsage(usage);
|
||||
}
|
||||
}
|
||||
|
||||
private void replaceAtMatchingUsages(Node other, Predicate<Node> filter, Node toBeDeleted) {
|
||||
assert filter != null;
|
||||
assert checkReplaceWith(other);
|
||||
int i = 0;
|
||||
while (i < this.getUsageCount()) {
|
||||
Node usage = this.getUsageAt(i);
|
||||
if (filter == null || filter.test(usage)) {
|
||||
replaceAtUsage(other, toBeDeleted, usage);
|
||||
this.movUsageFromEndTo(i);
|
||||
} else {
|
||||
++i;
|
||||
@ -641,21 +705,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
|
||||
public void replaceAtMatchingUsages(Node other, NodePredicate usagePredicate) {
|
||||
assert checkReplaceWith(other);
|
||||
int index = 0;
|
||||
while (index < this.getUsageCount()) {
|
||||
Node usage = getUsageAt(index);
|
||||
if (usagePredicate.apply(usage)) {
|
||||
boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other);
|
||||
assert assertTrue(result, "not found in inputs, usage: %s", usage);
|
||||
if (other != null) {
|
||||
maybeNotifyInputChanged(usage);
|
||||
other.addUsage(usage);
|
||||
}
|
||||
this.movUsageFromEndTo(index);
|
||||
} else {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
replaceAtMatchingUsages(other, usagePredicate, null);
|
||||
}
|
||||
|
||||
public void replaceAtUsages(InputType type, Node other) {
|
||||
|
@ -154,7 +154,7 @@ public final class NodeBitMap implements NodeIterable<Node> {
|
||||
if (bits.length < other.bits.length) {
|
||||
bits = Arrays.copyOf(bits, other.bits.length);
|
||||
}
|
||||
for (int i = 0; i < bits.length; i++) {
|
||||
for (int i = 0; i < Math.min(bits.length, other.bits.length); i++) {
|
||||
bits[i] |= other.bits[i];
|
||||
}
|
||||
}
|
||||
@ -181,44 +181,47 @@ public final class NodeBitMap implements NodeIterable<Node> {
|
||||
}
|
||||
}
|
||||
|
||||
private static class MarkedNodeIterator implements Iterator<Node> {
|
||||
protected int nextMarkedNodeId(int fromNodeId) {
|
||||
assert fromNodeId >= 0;
|
||||
int wordIndex = fromNodeId >> SHIFT;
|
||||
int wordsInUse = bits.length;
|
||||
if (wordIndex < wordsInUse) {
|
||||
long word = bits[wordIndex] & (0xFFFFFFFFFFFFFFFFL << fromNodeId);
|
||||
while (true) {
|
||||
if (word != 0) {
|
||||
return wordIndex * Long.SIZE + Long.numberOfTrailingZeros(word);
|
||||
}
|
||||
if (++wordIndex == wordsInUse) {
|
||||
break;
|
||||
}
|
||||
word = bits[wordIndex];
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
private final NodeBitMap visited;
|
||||
private Iterator<Node> nodes;
|
||||
private Node nextNode;
|
||||
private class MarkedNodeIterator implements Iterator<Node> {
|
||||
private int nextNodeId;
|
||||
|
||||
MarkedNodeIterator(NodeBitMap visited, Iterator<Node> nodes) {
|
||||
this.visited = visited;
|
||||
this.nodes = nodes;
|
||||
MarkedNodeIterator() {
|
||||
nextNodeId = -1;
|
||||
forward();
|
||||
}
|
||||
|
||||
private void forward() {
|
||||
do {
|
||||
if (!nodes.hasNext()) {
|
||||
nextNode = null;
|
||||
return;
|
||||
}
|
||||
nextNode = nodes.next();
|
||||
if (visited.isNew(nextNode)) {
|
||||
nextNode = null;
|
||||
return;
|
||||
}
|
||||
} while (!visited.isMarked(nextNode));
|
||||
nextNodeId = NodeBitMap.this.nextMarkedNodeId(nextNodeId + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return nextNode != null;
|
||||
return nextNodeId >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node next() {
|
||||
try {
|
||||
return nextNode;
|
||||
} finally {
|
||||
Node result = graph.getNode(nextNodeId);
|
||||
forward();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -230,7 +233,7 @@ public final class NodeBitMap implements NodeIterable<Node> {
|
||||
|
||||
@Override
|
||||
public Iterator<Node> iterator() {
|
||||
return new MarkedNodeIterator(NodeBitMap.this, graph().getNodes().iterator());
|
||||
return new MarkedNodeIterator();
|
||||
}
|
||||
|
||||
public NodeBitMap copy() {
|
||||
|
@ -599,23 +599,24 @@ public final class NodeClass<T> extends FieldIntrospection<T> {
|
||||
}
|
||||
|
||||
private static boolean deepEquals0(Object e1, Object e2) {
|
||||
assert e1 != null;
|
||||
if (e2 == null) {
|
||||
if (e1 == e2) {
|
||||
return true;
|
||||
} else if (e1 == null || e2 == null) {
|
||||
return false;
|
||||
} else if (e1 instanceof Object[] && e2 instanceof Object[]) {
|
||||
return Arrays.deepEquals((Object[]) e1, (Object[]) e2);
|
||||
} else if (!e1.getClass().isArray() || e1.getClass() != e2.getClass()) {
|
||||
return e1.equals(e2);
|
||||
} else if (e1 instanceof byte[]) {
|
||||
return Arrays.equals((byte[]) e1, (byte[]) e2);
|
||||
} else if (e1 instanceof short[]) {
|
||||
return Arrays.equals((short[]) e1, (short[]) e2);
|
||||
} else if (e1 instanceof Object[] && e2 instanceof Object[]) {
|
||||
return deepEquals((Object[]) e1, (Object[]) e2);
|
||||
} else if (e1 instanceof int[]) {
|
||||
return Arrays.equals((int[]) e1, (int[]) e2);
|
||||
} else if (e1 instanceof long[]) {
|
||||
return Arrays.equals((long[]) e1, (long[]) e2);
|
||||
} else if (e1 instanceof byte[]) {
|
||||
return Arrays.equals((byte[]) e1, (byte[]) e2);
|
||||
} else if (e1 instanceof char[]) {
|
||||
return Arrays.equals((char[]) e1, (char[]) e2);
|
||||
} else if (e1 instanceof short[]) {
|
||||
return Arrays.equals((short[]) e1, (short[]) e2);
|
||||
} else if (e1 instanceof float[]) {
|
||||
return Arrays.equals((float[]) e1, (float[]) e2);
|
||||
} else if (e1 instanceof double[]) {
|
||||
@ -627,6 +628,20 @@ public final class NodeClass<T> extends FieldIntrospection<T> {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean deepEquals(Object[] a1, Object[] a2) {
|
||||
int length = a1.length;
|
||||
if (a2.length != length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (!deepEquals0(a1[i], a2[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean dataEquals(Node a, Node b) {
|
||||
assert a.getClass() == b.getClass();
|
||||
for (int i = 0; i < data.getCount(); ++i) {
|
||||
|
@ -23,14 +23,17 @@
|
||||
package org.graalvm.compiler.graph;
|
||||
|
||||
public final class NodeStack {
|
||||
|
||||
private static final int INITIAL_SIZE = 8;
|
||||
private static final int DEFAULT_INITIAL_SIZE = 8;
|
||||
|
||||
protected Node[] values;
|
||||
public int tos;
|
||||
|
||||
public NodeStack() {
|
||||
values = new Node[INITIAL_SIZE];
|
||||
this(DEFAULT_INITIAL_SIZE);
|
||||
}
|
||||
|
||||
public NodeStack(int initialSize) {
|
||||
values = new Node[initialSize];
|
||||
}
|
||||
|
||||
public int size() {
|
||||
|
@ -27,7 +27,7 @@ import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Queue;
|
||||
|
||||
import org.graalvm.compiler.core.common.PermanentBailoutException;
|
||||
import org.graalvm.compiler.debug.Debug;
|
||||
|
||||
public abstract class NodeWorkList implements Iterable<Node> {
|
||||
|
||||
@ -72,26 +72,19 @@ public abstract class NodeWorkList implements Iterable<Node> {
|
||||
}
|
||||
|
||||
public static final class IterativeNodeWorkList extends NodeWorkList {
|
||||
private static final int HARD_ITERATION_LIMIT = 1_000_000;
|
||||
private static final int EXPLICIT_BITMAP_THRESHOLD = 10;
|
||||
protected NodeBitMap inQueue;
|
||||
|
||||
private int iterationLimit;
|
||||
private boolean hardLimit;
|
||||
private Node firstNoChange;
|
||||
private Node lastPull;
|
||||
private Node lastChain;
|
||||
|
||||
public IterativeNodeWorkList(Graph graph, boolean fill, int iterationLimitPerNode) {
|
||||
super(graph, fill);
|
||||
if (iterationLimitPerNode > 0) {
|
||||
assert iterationLimitPerNode > 0;
|
||||
long limit = (long) iterationLimitPerNode * graph.getNodeCount();
|
||||
iterationLimit = (int) Long.min(Integer.MAX_VALUE, limit);
|
||||
hardLimit = false;
|
||||
} else {
|
||||
iterationLimit = HARD_ITERATION_LIMIT;
|
||||
hardLimit = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -101,12 +94,9 @@ public abstract class NodeWorkList implements Iterable<Node> {
|
||||
public boolean hasNext() {
|
||||
dropDeleted();
|
||||
if (iterationLimit <= 0) {
|
||||
if (hardLimit) {
|
||||
throw new PermanentBailoutException("Iteration limit reached");
|
||||
} else {
|
||||
Debug.log(Debug.INFO_LEVEL, "Exceeded iteration limit in IterativeNodeWorkList");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !worklist.isEmpty();
|
||||
}
|
||||
|
||||
@ -152,7 +142,7 @@ public abstract class NodeWorkList implements Iterable<Node> {
|
||||
}
|
||||
}
|
||||
}
|
||||
assert checkInfiniteWork(node) : "Readded " + node;
|
||||
assert checkInfiniteWork(node) : "Re-added " + node;
|
||||
if (inQueue != null) {
|
||||
inQueue.markAndGrow(node);
|
||||
}
|
||||
|
@ -22,13 +22,20 @@
|
||||
*/
|
||||
package org.graalvm.compiler.graph.iterators;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.iterators.NodePredicates.AndPredicate;
|
||||
|
||||
public interface NodePredicate {
|
||||
public interface NodePredicate extends Predicate<Node> {
|
||||
|
||||
boolean apply(Node n);
|
||||
|
||||
@Override
|
||||
default boolean test(Node n) {
|
||||
return apply(n);
|
||||
}
|
||||
|
||||
default NodePredicate and(NodePredicate np) {
|
||||
return new AndPredicate(this, np);
|
||||
}
|
||||
|
@ -105,6 +105,7 @@ public abstract class NodePredicates {
|
||||
return !a.apply(n);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodePredicate negate() {
|
||||
return a;
|
||||
}
|
||||
@ -148,6 +149,7 @@ public abstract class NodePredicates {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodePredicate negate() {
|
||||
return new NegativeTypePredicate(this);
|
||||
}
|
||||
@ -183,6 +185,7 @@ public abstract class NodePredicates {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodePredicate negate() {
|
||||
return new PositiveTypePredicate(this);
|
||||
}
|
||||
|
@ -557,7 +557,7 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp
|
||||
LIR lir = getResult().getLIR();
|
||||
ArrayList<LIRInstruction> instructions = lir.getLIRforBlock(lir.getControlFlowGraph().getStartBlock());
|
||||
instructions.add(1, op);
|
||||
Debug.dump(Debug.INFO_LOG_LEVEL, lir, "created rescue dummy op");
|
||||
Debug.dump(Debug.INFO_LEVEL, lir, "created rescue dummy op");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ public class ClassSubstitutionsTests extends GraalCompilerTest {
|
||||
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
|
||||
compile(graph.method(), graph);
|
||||
assertNotInGraph(graph, Invoke.class);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet);
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, snippet);
|
||||
return graph;
|
||||
} catch (Throwable e) {
|
||||
throw Debug.handle(e);
|
||||
|
@ -47,7 +47,7 @@ public class CompileTheWorldTest extends GraalCompilerTest {
|
||||
System.setProperty(CompileTheWorld.LIMITMODS_PROPERTY_NAME, "java.base");
|
||||
OptionValues initialOptions = getInitialOptions();
|
||||
EconomicMap<OptionKey<?>, Object> compilationOptions = CompileTheWorld.parseOptions("Inline=false");
|
||||
new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, true, initialOptions, compilationOptions).compile();
|
||||
new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, false, initialOptions, compilationOptions).compile();
|
||||
assert ExitVMOnException.getValue(initialOptions) == originalSetting;
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest {
|
||||
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
|
||||
compile(graph.method(), graph);
|
||||
assertNotInGraph(graph, Invoke.class);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet);
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, snippet);
|
||||
return graph;
|
||||
} catch (Throwable e) {
|
||||
throw Debug.handle(e);
|
||||
@ -117,59 +117,32 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables these tests until we know how to dynamically export the {@code jdk.internal.reflect}
|
||||
* package from the {@code java.base} module to the unnamed module associated with
|
||||
* {@link AsmLoader}. Without such an export, the test fails as follows:
|
||||
*
|
||||
* <pre>
|
||||
* Caused by: java.lang.IllegalAccessError: class org.graalvm.compiler.hotspot.test.ConstantPoolTest
|
||||
* (in unnamed module @0x57599b23) cannot access class jdk.internal.reflect.ConstantPool (in
|
||||
* module java.base) because module java.base does not export jdk.internal.reflect to unnamed
|
||||
* module @0x57599b23
|
||||
* </pre>
|
||||
*/
|
||||
private static void assumeJDK8() {
|
||||
// Assume.assumeTrue(Java8OrEarlier);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSize() {
|
||||
assumeJDK8();
|
||||
Object cp = getConstantPoolForObject();
|
||||
test("getSize", cp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIntAt() {
|
||||
assumeJDK8();
|
||||
test("getIntAt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLongAt() {
|
||||
assumeJDK8();
|
||||
test("getLongAt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFloatAt() {
|
||||
assumeJDK8();
|
||||
test("getFloatAt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDoubleAt() {
|
||||
assumeJDK8();
|
||||
test("getDoubleAt");
|
||||
}
|
||||
|
||||
// @Test
|
||||
public void testGetUTF8At() {
|
||||
assumeJDK8();
|
||||
test("getUTF8At");
|
||||
}
|
||||
|
||||
private static final String PACKAGE_NAME = ConstantPoolSubstitutionsTests.class.getPackage().getName();
|
||||
private static final String PACKAGE_NAME_INTERNAL = PACKAGE_NAME.replace('.', '/');
|
||||
|
||||
|
@ -53,6 +53,7 @@ import org.graalvm.compiler.nodes.spi.LIRLowerable;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
|
||||
import jdk.vm.ci.code.BytecodeFrame;
|
||||
import jdk.vm.ci.code.CodeCacheProvider;
|
||||
import jdk.vm.ci.code.VirtualObject;
|
||||
import jdk.vm.ci.code.site.InfopointReason;
|
||||
import jdk.vm.ci.common.JVMCIError;
|
||||
@ -140,8 +141,9 @@ public class JVMCIInfopointErrorTest extends GraalCompilerTest {
|
||||
graph.addAfterFixed(graph.start(), test);
|
||||
|
||||
CompilationResult compResult = compile(method, graph);
|
||||
HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(method, null, compResult);
|
||||
getCodeCache().addCode(method, compiledCode, null, null);
|
||||
CodeCacheProvider codeCache = getCodeCache();
|
||||
HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, method, null, compResult);
|
||||
codeCache.addCode(method, compiledCode, null, null);
|
||||
}
|
||||
|
||||
@Test(expected = JVMCIError.class)
|
||||
|
@ -58,7 +58,11 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest {
|
||||
@Override
|
||||
@SuppressWarnings("try")
|
||||
protected Suites createSuites(OptionValues options) {
|
||||
return super.createSuites(new OptionValues(options, GraalOptions.ImmutableCode, true));
|
||||
return super.createSuites(getOptions());
|
||||
}
|
||||
|
||||
private static OptionValues getOptions() {
|
||||
return new OptionValues(getInitialOptions(), GraalOptions.ImmutableCode, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -77,7 +81,7 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest {
|
||||
|
||||
@Test
|
||||
public void testClassConstant() {
|
||||
test("classConstant");
|
||||
test(getOptions(), "classConstant");
|
||||
}
|
||||
|
||||
public static Class<?> primitiveClassConstant() {
|
||||
@ -86,7 +90,7 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest {
|
||||
|
||||
@Test
|
||||
public void testPrimitiveClassConstant() {
|
||||
test("primitiveClassConstant");
|
||||
test(getOptions(), "primitiveClassConstant");
|
||||
}
|
||||
|
||||
public static Wrapper compressedClassConstant(Wrapper w) {
|
||||
@ -97,7 +101,7 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest {
|
||||
@Test
|
||||
public void testCompressedClassConstant() {
|
||||
ArgSupplier arg = () -> new Wrapper();
|
||||
test("compressedClassConstant", arg);
|
||||
test(getOptions(), "compressedClassConstant", arg);
|
||||
}
|
||||
|
||||
public static Wrapper compressedPrimitiveClassConstant(Wrapper w) {
|
||||
@ -108,6 +112,6 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest {
|
||||
@Test
|
||||
public void testCompressedPrimitiveClassConstant() {
|
||||
ArgSupplier arg = () -> new Wrapper();
|
||||
test("compressedPrimitiveClassConstant", arg);
|
||||
test(getOptions(), "compressedPrimitiveClassConstant", arg);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2016, 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 static org.graalvm.compiler.test.SubprocessUtil.formatExecutedCommand;
|
||||
import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine;
|
||||
import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
import org.graalvm.compiler.hotspot.CompilationTask;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests {@link CompilationTask} support for dumping graphs and other info useful for debugging a
|
||||
* compiler crash.
|
||||
*/
|
||||
public class RetryableCompilationTest extends GraalCompilerTest {
|
||||
@Test
|
||||
public void test() throws IOException {
|
||||
List<String> args = withoutDebuggerArguments(getVMCommandLine());
|
||||
|
||||
args.add("-XX:+BootstrapJVMCI");
|
||||
args.add("-XX:+UseJVMCICompiler");
|
||||
args.add("-Dgraal.CrashAt=Object.*,String.*");
|
||||
args.add("-version");
|
||||
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(args);
|
||||
processBuilder.redirectErrorStream(true);
|
||||
Process process = processBuilder.start();
|
||||
BufferedReader stdout = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
|
||||
String forcedCrashString = "Forced crash after compiling";
|
||||
String diagnosticOutputFilePrefix = "Graal diagnostic output saved in ";
|
||||
|
||||
boolean seenForcedCrashString = false;
|
||||
String diagnosticOutputZip = null;
|
||||
|
||||
List<String> outputLines = new ArrayList<>();
|
||||
|
||||
String line;
|
||||
while ((line = stdout.readLine()) != null) {
|
||||
outputLines.add(line);
|
||||
if (line.contains(forcedCrashString)) {
|
||||
seenForcedCrashString = true;
|
||||
} else if (diagnosticOutputZip == null) {
|
||||
int index = line.indexOf(diagnosticOutputFilePrefix);
|
||||
if (index != -1) {
|
||||
diagnosticOutputZip = line.substring(diagnosticOutputFilePrefix.length()).trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
String dashes = "-------------------------------------------------------";
|
||||
if (!seenForcedCrashString) {
|
||||
Assert.fail(String.format("Did not find '%s' in output of command:%n%s", forcedCrashString, formatExecutedCommand(args, outputLines, dashes, dashes)));
|
||||
}
|
||||
if (diagnosticOutputZip == null) {
|
||||
Assert.fail(String.format("Did not find '%s' in output of command:%n%s", diagnosticOutputFilePrefix, formatExecutedCommand(args, outputLines, dashes, dashes)));
|
||||
}
|
||||
|
||||
File zip = new File(diagnosticOutputZip).getAbsoluteFile();
|
||||
Assert.assertTrue(zip.toString(), zip.exists());
|
||||
try {
|
||||
int bgv = 0;
|
||||
int cfg = 0;
|
||||
ZipFile dd = new ZipFile(diagnosticOutputZip);
|
||||
List<String> entries = new ArrayList<>();
|
||||
for (Enumeration<? extends ZipEntry> e = dd.entries(); e.hasMoreElements();) {
|
||||
ZipEntry ze = e.nextElement();
|
||||
String name = ze.getName();
|
||||
entries.add(name);
|
||||
if (name.endsWith(".bgv")) {
|
||||
bgv++;
|
||||
} else if (name.endsWith(".cfg")) {
|
||||
cfg++;
|
||||
}
|
||||
}
|
||||
if (bgv == 0) {
|
||||
Assert.fail(String.format("Expected at least one .bgv file in %s: %s", diagnosticOutputZip, entries));
|
||||
}
|
||||
if (cfg == 0) {
|
||||
Assert.fail(String.format("Expected at least one .cfg file in %s: %s", diagnosticOutputZip, entries));
|
||||
}
|
||||
} finally {
|
||||
zip.delete();
|
||||
}
|
||||
}
|
||||
}
|
@ -266,7 +266,7 @@ public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest {
|
||||
new GuardLoweringPhase().apply(graph, midContext);
|
||||
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext);
|
||||
new WriteBarrierAdditionPhase(config).apply(graph);
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After Write Barrier Addition");
|
||||
Debug.dump(Debug.BASIC_LEVEL, graph, "After Write Barrier Addition");
|
||||
|
||||
int barriers = 0;
|
||||
if (config.useG1GC) {
|
||||
|
@ -30,7 +30,20 @@ import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation;
|
||||
import static org.graalvm.compiler.core.GraalCompilerOptions.PrintFilter;
|
||||
import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException;
|
||||
import static org.graalvm.compiler.core.phases.HighTier.Options.Inline;
|
||||
import static org.graalvm.compiler.debug.Debug.INFO_LEVEL;
|
||||
import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.DUMP_METHOD;
|
||||
import static org.graalvm.compiler.debug.DelegatingDebugConfig.Level.DUMP;
|
||||
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump;
|
||||
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DumpPath;
|
||||
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.ForceDebugEnable;
|
||||
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintCFGFileName;
|
||||
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintGraphFile;
|
||||
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintGraphFileName;
|
||||
import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
@ -38,7 +51,9 @@ import org.graalvm.compiler.debug.Debug;
|
||||
import org.graalvm.compiler.debug.Debug.Scope;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugCounter;
|
||||
import org.graalvm.compiler.debug.DebugDumpHandler;
|
||||
import org.graalvm.compiler.debug.DebugDumpScope;
|
||||
import org.graalvm.compiler.debug.DebugRetryableTask;
|
||||
import org.graalvm.compiler.debug.DebugTimer;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.debug.Management;
|
||||
@ -46,6 +61,7 @@ import org.graalvm.compiler.debug.TTY;
|
||||
import org.graalvm.compiler.debug.TimeSource;
|
||||
import org.graalvm.compiler.options.OptionKey;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.printer.GraalDebugConfigCustomizer;
|
||||
import org.graalvm.util.EconomicMap;
|
||||
|
||||
import jdk.vm.ci.code.BailoutException;
|
||||
@ -96,6 +112,136 @@ public class CompilationTask {
|
||||
private final boolean useProfilingInfo;
|
||||
private final OptionValues options;
|
||||
|
||||
final class RetryableCompilation extends DebugRetryableTask<HotSpotCompilationRequestResult> {
|
||||
private final EventProvider.CompilationEvent compilationEvent;
|
||||
CompilationResult result;
|
||||
|
||||
RetryableCompilation(EventProvider.CompilationEvent compilationEvent) {
|
||||
this.compilationEvent = compilationEvent;
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
@Override
|
||||
protected HotSpotCompilationRequestResult run(Throwable retryCause) {
|
||||
HotSpotResolvedJavaMethod method = getMethod();
|
||||
int entryBCI = getEntryBCI();
|
||||
final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
|
||||
CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR);
|
||||
final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed();
|
||||
final boolean printAfterCompilation = PrintAfterCompilation.getValue(options) && !TTY.isSuppressed();
|
||||
if (printCompilation) {
|
||||
TTY.println(getMethodDescription() + "...");
|
||||
}
|
||||
|
||||
TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(options), method);
|
||||
final long start;
|
||||
final long allocatedBytesBefore;
|
||||
if (printAfterCompilation || printCompilation) {
|
||||
final long threadId = Thread.currentThread().getId();
|
||||
start = TimeSource.getTimeNS();
|
||||
allocatedBytesBefore = printAfterCompilation || printCompilation ? Lazy.threadMXBean.getThreadAllocatedBytes(threadId) : 0L;
|
||||
} else {
|
||||
start = 0L;
|
||||
allocatedBytesBefore = 0L;
|
||||
}
|
||||
|
||||
try (Scope s = Debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) {
|
||||
// Begin the compilation event.
|
||||
compilationEvent.begin();
|
||||
result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options);
|
||||
} catch (Throwable e) {
|
||||
throw Debug.handle(e);
|
||||
} finally {
|
||||
// End the compilation event.
|
||||
compilationEvent.end();
|
||||
|
||||
filter.remove();
|
||||
|
||||
if (printAfterCompilation || printCompilation) {
|
||||
final long threadId = Thread.currentThread().getId();
|
||||
final long stop = TimeSource.getTimeNS();
|
||||
final long duration = (stop - start) / 1000000;
|
||||
final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1;
|
||||
final int bytecodeSize = result != null ? result.getBytecodeSize() : 0;
|
||||
final long allocatedBytesAfter = Lazy.threadMXBean.getThreadAllocatedBytes(threadId);
|
||||
final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024;
|
||||
|
||||
if (printAfterCompilation) {
|
||||
TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes));
|
||||
} else if (printCompilation) {
|
||||
TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dB %5dkB", getId(), "", "", "", duration, bytecodeSize, targetCodeSize, allocatedKBytes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
try (DebugCloseable b = CodeInstallationTime.start()) {
|
||||
installMethod(result);
|
||||
}
|
||||
}
|
||||
stats.finish(method, installedCode);
|
||||
if (result != null) {
|
||||
return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onRetry(Throwable t) {
|
||||
if (t instanceof BailoutException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Debug.isEnabled()) {
|
||||
TTY.printf("Error while processing %s.%nRe-run with -D%s%s=true to capture graph dumps upon a compilation failure.%n", CompilationTask.this,
|
||||
HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX, ForceDebugEnable.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Dump.hasBeenSet(options)) {
|
||||
// If dumping is explicitly enabled, Graal is being debugged
|
||||
// so don't interfere with what the user is expecting to see.
|
||||
return false;
|
||||
}
|
||||
|
||||
String outputDirectory = compiler.getGraalRuntime().getOutputDirectory();
|
||||
if (outputDirectory == null) {
|
||||
return false;
|
||||
}
|
||||
String methodFQN = getMethod().format("%H.%n");
|
||||
File dumpPath = new File(outputDirectory, methodFQN);
|
||||
dumpPath.mkdirs();
|
||||
if (!dumpPath.exists()) {
|
||||
TTY.println("Warning: could not create dump directory " + dumpPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
TTY.println("Retrying " + CompilationTask.this);
|
||||
retryDumpHandlers = new ArrayList<>();
|
||||
retryOptions = new OptionValues(options,
|
||||
PrintGraphFile, true,
|
||||
PrintCFGFileName, methodFQN,
|
||||
PrintGraphFileName, methodFQN,
|
||||
DumpPath, dumpPath.getPath());
|
||||
override(DUMP, INFO_LEVEL).enable(DUMP_METHOD);
|
||||
new GraalDebugConfigCustomizer().customize(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
private Collection<DebugDumpHandler> retryDumpHandlers;
|
||||
private OptionValues retryOptions;
|
||||
|
||||
@Override
|
||||
public Collection<DebugDumpHandler> dumpHandlers() {
|
||||
return retryDumpHandlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OptionValues getOptions() {
|
||||
return retryOptions;
|
||||
}
|
||||
}
|
||||
|
||||
static class Lazy {
|
||||
/**
|
||||
* A {@link com.sun.management.ThreadMXBean} to be able to query some information about the
|
||||
@ -196,9 +342,8 @@ public class CompilationTask {
|
||||
public HotSpotCompilationRequestResult runCompilation() {
|
||||
HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime();
|
||||
GraalHotSpotVMConfig config = graalRuntime.getVMConfig();
|
||||
final long threadId = Thread.currentThread().getId();
|
||||
int entryBCI = getEntryBCI();
|
||||
final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
|
||||
boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
|
||||
HotSpotResolvedJavaMethod method = getMethod();
|
||||
|
||||
// register the compilation id in the method metrics
|
||||
@ -220,64 +365,9 @@ public class CompilationTask {
|
||||
return null;
|
||||
}
|
||||
|
||||
CompilationResult result = null;
|
||||
RetryableCompilation compilation = new RetryableCompilation(compilationEvent);
|
||||
try (DebugCloseable a = CompilationTime.start()) {
|
||||
CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR);
|
||||
final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed();
|
||||
final boolean printAfterCompilation = PrintAfterCompilation.getValue(options) && !TTY.isSuppressed();
|
||||
if (printCompilation) {
|
||||
TTY.println(getMethodDescription() + "...");
|
||||
}
|
||||
|
||||
TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(options), method);
|
||||
final long start;
|
||||
final long allocatedBytesBefore;
|
||||
if (printAfterCompilation || printCompilation) {
|
||||
start = TimeSource.getTimeNS();
|
||||
allocatedBytesBefore = printAfterCompilation || printCompilation ? Lazy.threadMXBean.getThreadAllocatedBytes(threadId) : 0L;
|
||||
} else {
|
||||
start = 0L;
|
||||
allocatedBytesBefore = 0L;
|
||||
}
|
||||
|
||||
try (Scope s = Debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) {
|
||||
// Begin the compilation event.
|
||||
compilationEvent.begin();
|
||||
result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options);
|
||||
} catch (Throwable e) {
|
||||
throw Debug.handle(e);
|
||||
} finally {
|
||||
// End the compilation event.
|
||||
compilationEvent.end();
|
||||
|
||||
filter.remove();
|
||||
|
||||
if (printAfterCompilation || printCompilation) {
|
||||
final long stop = TimeSource.getTimeNS();
|
||||
final long duration = (stop - start) / 1000000;
|
||||
final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1;
|
||||
final int bytecodeSize = result != null ? result.getBytecodeSize() : 0;
|
||||
final long allocatedBytesAfter = Lazy.threadMXBean.getThreadAllocatedBytes(threadId);
|
||||
final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024;
|
||||
|
||||
if (printAfterCompilation) {
|
||||
TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes));
|
||||
} else if (printCompilation) {
|
||||
TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dB %5dkB", getId(), "", "", "", duration, bytecodeSize, targetCodeSize, allocatedKBytes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
try (DebugCloseable b = CodeInstallationTime.start()) {
|
||||
installMethod(result);
|
||||
}
|
||||
}
|
||||
stats.finish(method, installedCode);
|
||||
if (result != null) {
|
||||
return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize());
|
||||
}
|
||||
return null;
|
||||
return compilation.execute();
|
||||
} catch (BailoutException bailout) {
|
||||
BAILOUTS.increment();
|
||||
if (ExitVMOnBailout.getValue(options)) {
|
||||
@ -319,8 +409,9 @@ public class CompilationTask {
|
||||
try {
|
||||
int compiledBytecodes = 0;
|
||||
int codeSize = 0;
|
||||
if (result != null) {
|
||||
compiledBytecodes = result.getBytecodeSize();
|
||||
|
||||
if (compilation.result != null) {
|
||||
compiledBytecodes = compilation.result.getBytecodeSize();
|
||||
CompiledBytecodes.add(compiledBytecodes);
|
||||
if (installedCode != null) {
|
||||
codeSize = installedCode.getSize();
|
||||
@ -334,7 +425,7 @@ public class CompilationTask {
|
||||
compilationEvent.setMethod(method.format("%H.%n(%p)"));
|
||||
compilationEvent.setCompileId(getId());
|
||||
compilationEvent.setCompileLevel(config.compilationLevelFullOptimization);
|
||||
compilationEvent.setSucceeded(result != null && installedCode != null);
|
||||
compilationEvent.setSucceeded(compilation.result != null && installedCode != null);
|
||||
compilationEvent.setIsOsr(isOSR);
|
||||
compilationEvent.setCodeSize(codeSize);
|
||||
compilationEvent.setInlinedBytes(compiledBytecodes);
|
||||
@ -387,7 +478,7 @@ public class CompilationTask {
|
||||
installedCode = null;
|
||||
Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult};
|
||||
try (Scope s = Debug.scope("CodeInstall", context)) {
|
||||
HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(getRequest().getMethod(), getRequest(), compResult);
|
||||
HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, getRequest().getMethod(), getRequest(), compResult);
|
||||
installedCode = (HotSpotInstalledCode) codeCache.installCode(getRequest().getMethod(), compiledCode, null, getRequest().getMethod().getSpeculationLog(), installAsDefault);
|
||||
} catch (Throwable e) {
|
||||
throw Debug.handle(e);
|
||||
|
@ -267,7 +267,31 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||
public final int secondarySuperCacheOffset = getFieldOffset("Klass::_secondary_super_cache", Integer.class, "Klass*");
|
||||
public final int secondarySupersOffset = getFieldOffset("Klass::_secondary_supers", Integer.class, "Array<Klass*>*");
|
||||
|
||||
public final int classMirrorOffset = getFieldOffset("Klass::_java_mirror", Integer.class, "oop");
|
||||
public final boolean classMirrorIsHandle;
|
||||
public final int classMirrorOffset;
|
||||
{
|
||||
String name = "Klass::_java_mirror";
|
||||
int offset = -1;
|
||||
boolean isHandle = false;
|
||||
try {
|
||||
offset = getFieldOffset(name, Integer.class, "oop");
|
||||
} catch (JVMCIError e) {
|
||||
|
||||
}
|
||||
if (offset == -1) {
|
||||
try {
|
||||
offset = getFieldOffset(name, Integer.class, "jobject");
|
||||
isHandle = true;
|
||||
} catch (JVMCIError e) {
|
||||
|
||||
}
|
||||
}
|
||||
if (offset == -1) {
|
||||
throw new JVMCIError("cannot get offset of field " + name + " with type oop or jobject");
|
||||
}
|
||||
classMirrorOffset = offset;
|
||||
classMirrorIsHandle = isHandle;
|
||||
}
|
||||
|
||||
public final int klassSuperKlassOffset = getFieldOffset("Klass::_super", Integer.class, "Klass*");
|
||||
public final int klassModifierFlagsOffset = getFieldOffset("Klass::_modifier_flags", Integer.class, "jint");
|
||||
|
@ -406,7 +406,7 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen
|
||||
@Override
|
||||
public CompiledCode createCompiledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compResult) {
|
||||
HotSpotCompilationRequest compRequest = compilationRequest instanceof HotSpotCompilationRequest ? (HotSpotCompilationRequest) compilationRequest : null;
|
||||
return HotSpotCompiledCodeBuilder.createCompiledCode(method, compRequest, compResult);
|
||||
return HotSpotCompiledCodeBuilder.createCompiledCode(getCodeCache(), method, compRequest, compResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -42,6 +42,7 @@ import org.graalvm.compiler.code.DataSection;
|
||||
import org.graalvm.compiler.code.SourceMapping;
|
||||
import org.graalvm.compiler.graph.NodeSourcePosition;
|
||||
|
||||
import jdk.vm.ci.code.CodeCacheProvider;
|
||||
import jdk.vm.ci.code.DebugInfo;
|
||||
import jdk.vm.ci.code.StackSlot;
|
||||
import jdk.vm.ci.code.site.ConstantReference;
|
||||
@ -61,13 +62,13 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
public class HotSpotCompiledCodeBuilder {
|
||||
|
||||
public static HotSpotCompiledCode createCompiledCode(ResolvedJavaMethod method, HotSpotCompilationRequest compRequest, CompilationResult compResult) {
|
||||
public static HotSpotCompiledCode createCompiledCode(CodeCacheProvider codeCache, ResolvedJavaMethod method, HotSpotCompilationRequest compRequest, CompilationResult compResult) {
|
||||
String name = compResult.getName();
|
||||
|
||||
byte[] targetCode = compResult.getTargetCode();
|
||||
int targetCodeSize = compResult.getTargetCodeSize();
|
||||
|
||||
Site[] sites = getSortedSites(compResult);
|
||||
Site[] sites = getSortedSites(codeCache, compResult);
|
||||
|
||||
Assumption[] assumptions = compResult.getAssumptions();
|
||||
|
||||
@ -201,7 +202,7 @@ public class HotSpotCompiledCodeBuilder {
|
||||
* {@code DebugInformationRecorder::add_new_pc_offset}). In addition, it expects
|
||||
* {@link Infopoint} PCs to be unique.
|
||||
*/
|
||||
private static Site[] getSortedSites(CompilationResult target) {
|
||||
private static Site[] getSortedSites(CodeCacheProvider codeCache, CompilationResult target) {
|
||||
List<Site> sites = new ArrayList<>(
|
||||
target.getExceptionHandlers().size() + target.getInfopoints().size() + target.getDataPatches().size() + target.getMarks().size() + target.getSourceMappings().size());
|
||||
sites.addAll(target.getExceptionHandlers());
|
||||
@ -214,10 +215,12 @@ public class HotSpotCompiledCodeBuilder {
|
||||
* can really be represented and recording the end PC seems to give the best results and
|
||||
* corresponds with what C1 and C2 do.
|
||||
*/
|
||||
if (codeCache.shouldDebugNonSafepoints()) {
|
||||
for (SourceMapping source : target.getSourceMappings()) {
|
||||
sites.add(new Infopoint(source.getEndOffset(), new DebugInfo(source.getSourcePosition()), InfopointReason.BYTECODE_POSITION));
|
||||
assert verifySourcePositionReceivers(source.getSourcePosition());
|
||||
}
|
||||
}
|
||||
|
||||
SiteComparator c = new SiteComparator();
|
||||
Collections.sort(sites, c);
|
||||
|
@ -71,8 +71,8 @@ public class HotSpotDebugInfoBuilder extends DebugInfoBuilder {
|
||||
VirtualStackSlot slot = lockStack.makeLockSlot(lockDepth);
|
||||
ValueNode lock = state.lockAt(lockIndex);
|
||||
JavaValue object = toJavaValue(lock);
|
||||
boolean eliminated = object instanceof VirtualObject || state.monitorIdAt(lockIndex) == null;
|
||||
assert state.monitorIdAt(lockIndex) == null || state.monitorIdAt(lockIndex).getLockDepth() == lockDepth;
|
||||
boolean eliminated = object instanceof VirtualObject || state.monitorIdAt(lockIndex).isEliminated();
|
||||
assert state.monitorIdAt(lockIndex).getLockDepth() == lockDepth;
|
||||
return new StackLockValue(object, slot, eliminated);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ package org.graalvm.compiler.hotspot;
|
||||
|
||||
import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions;
|
||||
import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Formattable;
|
||||
@ -98,6 +99,9 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler {
|
||||
@Override
|
||||
@SuppressWarnings("try")
|
||||
public CompilationRequestResult compileMethod(CompilationRequest request) {
|
||||
if (graalRuntime.isShutdown()) {
|
||||
return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), false);
|
||||
}
|
||||
OptionValues options = graalRuntime.getOptions();
|
||||
if (graalRuntime.isBootstrapping()) {
|
||||
if (GraalDebugConfig.Options.BootstrapInitializeOnly.getValue(options)) {
|
||||
|
@ -45,6 +45,7 @@ import jdk.vm.ci.services.Services;
|
||||
public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFactory {
|
||||
|
||||
private static MethodFilter[] graalCompileOnlyFilter;
|
||||
private static boolean compileGraalWithC1Only;
|
||||
|
||||
private final HotSpotGraalJVMCIServiceLocator locator;
|
||||
|
||||
@ -67,8 +68,7 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto
|
||||
JVMCIVersionCheck.check(false);
|
||||
assert options == null : "cannot select " + getClass() + " service more than once";
|
||||
options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
|
||||
initializeGraalCompileOnlyFilter(options);
|
||||
if (graalCompileOnlyFilter != null || !Options.UseTrivialPrefixes.getValue(options)) {
|
||||
initializeGraalCompilePolicyFields(options);
|
||||
/*
|
||||
* Exercise this code path early to encourage loading now. This doesn't solve problem of
|
||||
* deadlock during class loading but seems to eliminate it in practice.
|
||||
@ -76,9 +76,9 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto
|
||||
adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization);
|
||||
adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initializeGraalCompileOnlyFilter(OptionValues options) {
|
||||
private static void initializeGraalCompilePolicyFields(OptionValues options) {
|
||||
compileGraalWithC1Only = Options.CompileGraalWithC1Only.getValue(options);
|
||||
String optionValue = Options.GraalCompileOnly.getValue(options);
|
||||
if (optionValue != null) {
|
||||
MethodFilter[] filter = MethodFilter.parse(optionValue);
|
||||
@ -101,9 +101,6 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto
|
||||
@Option(help = "In tiered mode compile Graal and JVMCI using optimized first tier code.", type = OptionType.Expert)
|
||||
public static final OptionKey<Boolean> CompileGraalWithC1Only = new OptionKey<>(true);
|
||||
|
||||
@Option(help = "Hook into VM-level mechanism for denoting compilations to be performed in first tier.", type = OptionType.Expert)
|
||||
public static final OptionKey<Boolean> UseTrivialPrefixes = new OptionKey<>(false);
|
||||
|
||||
@Option(help = "A method filter selecting what should be compiled by Graal. All other requests will be reduced to CompilationLevel.Simple.", type = OptionType.Expert)
|
||||
public static final OptionKey<String> GraalCompileOnly = new OptionKey<>(null);
|
||||
// @formatter:on
|
||||
@ -136,29 +133,17 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getTrivialPrefixes() {
|
||||
if (Options.UseTrivialPrefixes.getValue(options)) {
|
||||
if (Options.CompileGraalWithC1Only.getValue(options)) {
|
||||
return new String[]{"jdk/vm/ci", "org/graalvm/compiler", "com/oracle/graal"};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilationLevelAdjustment getCompilationLevelAdjustment() {
|
||||
if (graalCompileOnlyFilter != null) {
|
||||
return CompilationLevelAdjustment.ByFullSignature;
|
||||
}
|
||||
if (!Options.UseTrivialPrefixes.getValue(options)) {
|
||||
if (Options.CompileGraalWithC1Only.getValue(options)) {
|
||||
if (compileGraalWithC1Only) {
|
||||
// We only decide using the class declaring the method
|
||||
// so no need to have the method name and signature
|
||||
// symbols converted to a String.
|
||||
return CompilationLevelAdjustment.ByHolder;
|
||||
}
|
||||
}
|
||||
return CompilationLevelAdjustment.None;
|
||||
}
|
||||
|
||||
@ -193,12 +178,14 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto
|
||||
return CompilationLevel.Simple;
|
||||
}
|
||||
}
|
||||
if (compileGraalWithC1Only) {
|
||||
if (level.ordinal() > CompilationLevel.Simple.ordinal()) {
|
||||
String declaringClassName = declaringClass.getName();
|
||||
if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm.compiler") || declaringClassName.startsWith("com.oracle.graal")) {
|
||||
if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm") || declaringClassName.startsWith("com.oracle.graal")) {
|
||||
return CompilationLevel.Simple;
|
||||
}
|
||||
}
|
||||
}
|
||||
return level;
|
||||
}
|
||||
}
|
||||
|
@ -30,20 +30,28 @@ import static org.graalvm.compiler.core.common.util.Util.JAVA_SPECIFICATION_VERS
|
||||
import org.graalvm.compiler.serviceprovider.ServiceProvider;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotVMEventListener;
|
||||
import jdk.vm.ci.runtime.JVMCICompiler;
|
||||
import jdk.vm.ci.runtime.JVMCICompilerFactory;
|
||||
import jdk.vm.ci.services.JVMCIServiceLocator;
|
||||
import jdk.vm.ci.services.Services;
|
||||
|
||||
@ServiceProvider(JVMCIServiceLocator.class)
|
||||
public final class HotSpotGraalJVMCIServiceLocator extends JVMCIServiceLocator {
|
||||
|
||||
/**
|
||||
* Holds the state shared between all {@link HotSpotGraalJVMCIServiceLocator} instances. This is
|
||||
* necessary as {@link Services} can create a new instance of a service provider each time
|
||||
* {@link Services#load(Class)} or {@link Services#loadSingle(Class, boolean)} is called.
|
||||
*/
|
||||
private static final class Shared {
|
||||
static final Shared SINGLETON = new Shared();
|
||||
|
||||
private boolean exportsAdded;
|
||||
|
||||
/**
|
||||
* Dynamically exports and opens various internal JDK packages to the Graal module. This
|
||||
* requires only a single {@code --add-exports=java.base/jdk.internal.module=<Graal module>} on
|
||||
* the VM command line instead of a {@code --add-exports} instance for each JDK internal package
|
||||
* used by Graal.
|
||||
* requires only a single {@code --add-exports=java.base/jdk.internal.module=<Graal module>}
|
||||
* on the VM command line instead of a {@code --add-exports} instance for each JDK internal
|
||||
* package used by Graal.
|
||||
*/
|
||||
private void addExports() {
|
||||
if (JAVA_SPECIFICATION_VERSION >= 9 && !exportsAdded) {
|
||||
@ -59,13 +67,10 @@ public final class HotSpotGraalJVMCIServiceLocator extends JVMCIServiceLocator {
|
||||
}
|
||||
}
|
||||
|
||||
private HotSpotGraalRuntime graalRuntime;
|
||||
|
||||
@Override
|
||||
public <T> T getProvider(Class<T> service) {
|
||||
<T> T getProvider(Class<T> service, HotSpotGraalJVMCIServiceLocator locator) {
|
||||
if (service == JVMCICompilerFactory.class) {
|
||||
addExports();
|
||||
return service.cast(new HotSpotGraalCompilerFactory(this));
|
||||
return service.cast(new HotSpotGraalCompilerFactory(locator));
|
||||
} else if (service == HotSpotVMEventListener.class) {
|
||||
if (graalRuntime != null) {
|
||||
addExports();
|
||||
@ -75,23 +80,27 @@ public final class HotSpotGraalJVMCIServiceLocator extends JVMCIServiceLocator {
|
||||
return null;
|
||||
}
|
||||
|
||||
private HotSpotGraalRuntime graalRuntime;
|
||||
|
||||
/**
|
||||
* The signature cannot mention HotSpotGraalCompiler since it indirectly references
|
||||
* JVMCICompiler which is in a non-exported JVMCI package. This causes an IllegalAccessError
|
||||
* while looking for the
|
||||
* <a href="http://hg.openjdk.java.net/jdk9/hs/jdk/rev/89ef4b822745#l32.65">provider</a> factory
|
||||
* method:
|
||||
*
|
||||
* <pre>
|
||||
* java.util.ServiceConfigurationError: jdk.vm.ci.services.JVMCIServiceLocator: Unable to get public provider() method
|
||||
* ...
|
||||
* Caused by: java.lang.IllegalAccessError: superinterface check failed: class org.graalvm.compiler.api.runtime.GraalJVMCICompiler
|
||||
* (in module org.graalvm.compiler.graal_core) cannot access class jdk.vm.ci.runtime.JVMCICompiler (in module jdk.vm.ci) because
|
||||
* module jdk.vm.ci does not export jdk.vm.ci.runtime to module org.graalvm.compiler.graal_core
|
||||
* </pre>
|
||||
* Notifies this object of the compiler created via {@link HotSpotGraalJVMCIServiceLocator}.
|
||||
*/
|
||||
void onCompilerCreation(JVMCICompiler compiler) {
|
||||
void onCompilerCreation(HotSpotGraalCompiler compiler) {
|
||||
assert this.graalRuntime == null : "only expect a single JVMCICompiler to be created";
|
||||
this.graalRuntime = (HotSpotGraalRuntime) ((HotSpotGraalCompiler) compiler).getGraalRuntime();
|
||||
this.graalRuntime = (HotSpotGraalRuntime) compiler.getGraalRuntime();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getProvider(Class<T> service) {
|
||||
return Shared.SINGLETON.getProvider(service, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies this object of the compiler created via {@link HotSpotGraalJVMCIServiceLocator}.
|
||||
*/
|
||||
@SuppressWarnings("static-method")
|
||||
void onCompilerCreation(HotSpotGraalCompiler compiler) {
|
||||
Shared.SINGLETON.onCompilerCreation(compiler);
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,22 @@ import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Log;
|
||||
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodFilter;
|
||||
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Verify;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
|
||||
import org.graalvm.compiler.api.runtime.GraalRuntime;
|
||||
@ -278,6 +292,7 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
|
||||
}
|
||||
|
||||
private long runtimeStartTime;
|
||||
private boolean shutdown;
|
||||
|
||||
/**
|
||||
* Take action related to entering a new execution phase.
|
||||
@ -291,6 +306,7 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
shutdown = true;
|
||||
if (debugValuesPrinter != null) {
|
||||
debugValuesPrinter.printDebugValues(options);
|
||||
}
|
||||
@ -302,6 +318,8 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
|
||||
}
|
||||
}
|
||||
BenchmarkCounters.shutdown(runtime(), options, runtimeStartTime);
|
||||
|
||||
archiveAndDeleteOutputDirectory();
|
||||
}
|
||||
|
||||
void clearMeters() {
|
||||
@ -321,4 +339,95 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
|
||||
public boolean isBootstrapping() {
|
||||
return bootstrapJVMCI && !bootstrapFinished;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShutdown() {
|
||||
return shutdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a unique identifier for this execution such as a process ID.
|
||||
*/
|
||||
private static String getExecutionID() {
|
||||
String runtimeName = ManagementFactory.getRuntimeMXBean().getName();
|
||||
try {
|
||||
int index = runtimeName.indexOf('@');
|
||||
if (index != -1) {
|
||||
long pid = Long.parseLong(runtimeName.substring(0, index));
|
||||
return Long.toString(pid);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
return runtimeName;
|
||||
}
|
||||
|
||||
private String outputDirectory;
|
||||
|
||||
@Override
|
||||
public String getOutputDirectory() {
|
||||
if (outputDirectory == null) {
|
||||
outputDirectory = "graal_output_" + getExecutionID();
|
||||
File dir = new File(outputDirectory).getAbsoluteFile();
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
if (!dir.exists()) {
|
||||
TTY.println("Warning: could not create Graal diagnostic directory " + dir);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return outputDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Archives and deletes the {@linkplain #getOutputDirectory() output directory} if it exists.
|
||||
*/
|
||||
private void archiveAndDeleteOutputDirectory() {
|
||||
if (outputDirectory != null) {
|
||||
Path dir = Paths.get(outputDirectory);
|
||||
if (dir.toFile().exists()) {
|
||||
try {
|
||||
// Give compiler threads a chance to finishing dumping
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e1) {
|
||||
}
|
||||
File zip = new File(outputDirectory + ".zip").getAbsoluteFile();
|
||||
List<Path> toDelete = new ArrayList<>();
|
||||
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip))) {
|
||||
zos.setLevel(Deflater.BEST_COMPRESSION);
|
||||
Files.walkFileTree(dir, Collections.emptySet(), Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
if (attrs.isRegularFile()) {
|
||||
ZipEntry ze = new ZipEntry(file.toString());
|
||||
zos.putNextEntry(ze);
|
||||
zos.write(Files.readAllBytes(file));
|
||||
zos.closeEntry();
|
||||
}
|
||||
toDelete.add(file);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path d, IOException exc) throws IOException {
|
||||
toDelete.add(d);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
TTY.println("Graal diagnostic output saved in %s", zip);
|
||||
} catch (IOException e) {
|
||||
TTY.printf("IO error archiving %s:%n", dir);
|
||||
e.printStackTrace(TTY.out);
|
||||
}
|
||||
for (Path p : toDelete) {
|
||||
try {
|
||||
Files.delete(p);
|
||||
} catch (IOException e) {
|
||||
TTY.printf("IO error deleting %s:%n", p);
|
||||
e.printStackTrace(TTY.out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,4 +62,19 @@ public interface HotSpotGraalRuntimeProvider extends GraalRuntime, RuntimeProvid
|
||||
* Determines if the VM is currently bootstrapping the JVMCI compiler.
|
||||
*/
|
||||
boolean isBootstrapping();
|
||||
|
||||
/**
|
||||
* This runtime has been requested to shutdown.
|
||||
*/
|
||||
boolean isShutdown();
|
||||
|
||||
/**
|
||||
* Gets a directory into which diagnostics such crash reports and dumps should be written. This
|
||||
* method will create the directory if it doesn't exist so it should only be called if
|
||||
* diagnostics are about to be generated.
|
||||
*
|
||||
* @return the directory into which diagnostics can be written or {@code null} if the directory
|
||||
* does not exist and could not be created
|
||||
*/
|
||||
String getOutputDirectory();
|
||||
}
|
||||
|
@ -46,10 +46,10 @@ public class HotSpotGraalVMEventListener implements HotSpotVMEventListener {
|
||||
|
||||
@Override
|
||||
public void notifyInstall(HotSpotCodeCacheProvider codeCache, InstalledCode installedCode, CompiledCode compiledCode) {
|
||||
if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) {
|
||||
if (Debug.isDumpEnabled(Debug.BASIC_LEVEL)) {
|
||||
CompilationResult compResult = Debug.contextLookup(CompilationResult.class);
|
||||
assert compResult != null : "can't dump installed code properly without CompilationResult";
|
||||
Debug.dump(Debug.BASIC_LOG_LEVEL, installedCode, "After code installation");
|
||||
Debug.dump(Debug.BASIC_LEVEL, installedCode, "After code installation");
|
||||
}
|
||||
if (Debug.isLogEnabled()) {
|
||||
Debug.log("%s", codeCache.disassemble(installedCode));
|
||||
|
@ -45,7 +45,7 @@ public class PrintStreamOptionKey extends OptionKey<String> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace any instance of %p with a an identifying name. Try to get it from the RuntimeMXBean
|
||||
* Replace any instance of %p with an identifying name. Try to get it from the RuntimeMXBean
|
||||
* name.
|
||||
*
|
||||
* @return the name of the file to log to
|
||||
|
@ -31,6 +31,7 @@ import static org.graalvm.compiler.core.common.LocationIdentity.any;
|
||||
import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_KLASS_LOCATION;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_LOCATION;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_HANDLE_LOCATION;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.COMPRESSED_HUB_LOCATION;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.DISPLACED_MARK_WORD_LOCATION;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_LOCATION;
|
||||
@ -40,6 +41,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.
|
||||
import java.lang.ref.Reference;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.graalvm.compiler.core.common.GraalOptions;
|
||||
import org.graalvm.compiler.core.common.LocationIdentity;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
|
||||
@ -409,10 +411,17 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider
|
||||
return;
|
||||
}
|
||||
|
||||
ValueNode hub = n.getHub();
|
||||
GraalHotSpotVMConfig vmConfig = runtime.getVMConfig();
|
||||
StructuredGraph graph = n.graph();
|
||||
assert !n.getHub().isConstant();
|
||||
AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getVMConfig().classMirrorOffset);
|
||||
FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, n.stamp(), null, BarrierType.NONE));
|
||||
assert !hub.isConstant() || GraalOptions.ImmutableCode.getValue(graph.getOptions());
|
||||
AddressNode mirrorAddress = createOffsetAddress(graph, hub, vmConfig.classMirrorOffset);
|
||||
FloatingReadNode read = graph.unique(new FloatingReadNode(mirrorAddress, CLASS_MIRROR_LOCATION, null, vmConfig.classMirrorIsHandle ? StampFactory.forKind(target.wordJavaKind) : n.stamp(),
|
||||
null, BarrierType.NONE));
|
||||
if (vmConfig.classMirrorIsHandle) {
|
||||
AddressNode address = createOffsetAddress(graph, read, 0);
|
||||
read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_HANDLE_LOCATION, null, n.stamp(), null, BarrierType.NONE));
|
||||
}
|
||||
n.replaceAtUsagesAndDelete(read);
|
||||
}
|
||||
|
||||
|
@ -323,7 +323,8 @@ public class HotSpotGraphBuilderPlugins {
|
||||
*/
|
||||
private static ValueNode getMetaspaceConstantPool(GraphBuilderContext b, ValueNode constantPoolOop, WordTypes wordTypes, GraalHotSpotVMConfig config) {
|
||||
// ConstantPool.constantPoolOop is in fact the holder class.
|
||||
ClassGetHubNode klass = b.add(new ClassGetHubNode(b.nullCheckedValue(constantPoolOop, DeoptimizationAction.None)));
|
||||
ValueNode value = b.nullCheckedValue(constantPoolOop, DeoptimizationAction.None);
|
||||
ValueNode klass = b.add(ClassGetHubNode.create(value, b.getMetaAccess(), b.getConstantReflection(), false));
|
||||
|
||||
boolean notCompressible = false;
|
||||
AddressNode constantsAddress = b.add(new OffsetAddressNode(klass, b.add(ConstantNode.forLong(config.instanceKlassConstantsOffset))));
|
||||
|
@ -90,7 +90,7 @@ public class HotSpotSuitesProvider extends SuitesProviderBase {
|
||||
|
||||
if (ImmutableCode.getValue(options)) {
|
||||
// lowering introduces class constants, therefore it must be after lowering
|
||||
ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config.classMirrorOffset, config.useCompressedOops ? config.getOopEncoding() : null));
|
||||
ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config));
|
||||
if (VerifyPhases.getValue(options)) {
|
||||
ret.getHighTier().appendPhase(new AheadOfTimeVerificationPhase());
|
||||
}
|
||||
@ -146,10 +146,10 @@ public class HotSpotSuitesProvider extends SuitesProviderBase {
|
||||
protected void run(StructuredGraph graph, HighTierContext context) {
|
||||
EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, runtime.getTarget().arch);
|
||||
|
||||
SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(context.getMetaAccess(), context.getConstantReflection(), context.getConstantFieldProvider(),
|
||||
context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions()), runtime.getTarget().arch);
|
||||
StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), AllowAssumptions.YES).method(graph.method()).build();
|
||||
graphDecoder.decode(targetGraph, encodedGraph);
|
||||
SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context.getMetaAccess(), context.getConstantReflection(),
|
||||
context.getConstantFieldProvider(), context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions()));
|
||||
graphDecoder.decode(encodedGraph);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -109,7 +109,7 @@ class HotSpotWordOperationPlugin extends WordOperationPlugin {
|
||||
PointerEqualsNode comparison = b.add(new PointerEqualsNode(left, right));
|
||||
ValueNode eqValue = b.add(forBoolean(opcode == POINTER_EQ));
|
||||
ValueNode neValue = b.add(forBoolean(opcode == POINTER_NE));
|
||||
b.addPush(returnKind, new ConditionalNode(comparison, eqValue, neValue));
|
||||
b.addPush(returnKind, ConditionalNode.create(comparison, eqValue, neValue));
|
||||
break;
|
||||
|
||||
case IS_NULL:
|
||||
@ -118,7 +118,7 @@ class HotSpotWordOperationPlugin extends WordOperationPlugin {
|
||||
assert pointer.stamp() instanceof MetaspacePointerStamp;
|
||||
|
||||
LogicNode isNull = b.add(IsNullNode.create(pointer));
|
||||
b.addPush(returnKind, new ConditionalNode(isNull, b.add(forBoolean(true)), b.add(forBoolean(false))));
|
||||
b.addPush(returnKind, ConditionalNode.create(isNull, b.add(forBoolean(true)), b.add(forBoolean(false))));
|
||||
break;
|
||||
|
||||
case FROM_POINTER:
|
||||
|
@ -29,6 +29,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.Fold;
|
||||
import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
@ -72,8 +73,8 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab
|
||||
* @param config
|
||||
* @param markId id of the config value
|
||||
*/
|
||||
public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config, int markId) {
|
||||
super(TYPE, StampFactory.forNodeIntrinsic());
|
||||
public GraalHotSpotVMConfigNode(@InjectedNodeParameter Stamp stamp, @InjectedNodeParameter GraalHotSpotVMConfig config, int markId) {
|
||||
super(TYPE, stamp);
|
||||
this.config = config;
|
||||
this.markId = markId;
|
||||
}
|
||||
@ -85,7 +86,7 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab
|
||||
* @param markId id of the config value
|
||||
* @param kind explicit type of the node
|
||||
*/
|
||||
public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config, int markId, JavaKind kind) {
|
||||
public GraalHotSpotVMConfigNode(GraalHotSpotVMConfig config, int markId, JavaKind kind) {
|
||||
super(TYPE, StampFactory.forKind(kind));
|
||||
this.config = config;
|
||||
this.markId = markId;
|
||||
@ -100,13 +101,13 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab
|
||||
@NodeIntrinsic
|
||||
private static native boolean areConfigValuesConstant();
|
||||
|
||||
@NodeIntrinsic(setStampFromReturnType = true)
|
||||
@NodeIntrinsic
|
||||
private static native long loadLongConfigValue(@ConstantNodeParameter int markId);
|
||||
|
||||
@NodeIntrinsic(setStampFromReturnType = true)
|
||||
@NodeIntrinsic
|
||||
private static native int loadIntConfigValue(@ConstantNodeParameter int markId);
|
||||
|
||||
@NodeIntrinsic(setStampFromReturnType = true)
|
||||
@NodeIntrinsic
|
||||
private static native byte loadByteConfigValue(@ConstantNodeParameter int markId);
|
||||
|
||||
public static long cardTableAddress() {
|
||||
|
@ -32,7 +32,7 @@ import org.graalvm.compiler.core.common.LocationIdentity;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.graph.NodeInputList;
|
||||
import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil;
|
||||
@ -44,7 +44,6 @@ import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
|
||||
import org.graalvm.compiler.nodes.spi.LIRLowerable;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.Value;
|
||||
|
||||
/**
|
||||
@ -59,8 +58,8 @@ public final class StubForeignCallNode extends FixedWithNextNode implements LIRL
|
||||
|
||||
protected final ForeignCallDescriptor descriptor;
|
||||
|
||||
public StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) {
|
||||
super(TYPE, StampFactory.forKind(JavaKind.fromJavaClass(descriptor.getResultType())));
|
||||
public StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, @InjectedNodeParameter Stamp stamp, ForeignCallDescriptor descriptor, ValueNode... arguments) {
|
||||
super(TYPE, stamp);
|
||||
this.arguments = new NodeInputList<>(this, arguments);
|
||||
this.descriptor = descriptor;
|
||||
this.foreignCalls = foreignCalls;
|
||||
|
@ -22,6 +22,7 @@
|
||||
*/
|
||||
package org.graalvm.compiler.hotspot.nodes.aot;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
@ -44,8 +45,8 @@ public final class EncodedSymbolNode extends FloatingNode implements Canonicaliz
|
||||
|
||||
@OptionalInput protected ValueNode value;
|
||||
|
||||
public EncodedSymbolNode(ValueNode value) {
|
||||
super(TYPE, null);
|
||||
public EncodedSymbolNode(@InjectedNodeParameter Stamp stamp, ValueNode value) {
|
||||
super(TYPE, stamp);
|
||||
assert value != null;
|
||||
this.value = value;
|
||||
}
|
||||
@ -61,6 +62,6 @@ public final class EncodedSymbolNode extends FloatingNode implements Canonicaliz
|
||||
return this;
|
||||
}
|
||||
|
||||
@NodeIntrinsic(setStampFromReturnType = true)
|
||||
@NodeIntrinsic
|
||||
public static native Word encode(Object constant);
|
||||
}
|
||||
|
@ -22,7 +22,6 @@
|
||||
*/
|
||||
package org.graalvm.compiler.hotspot.phases;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_LOCATION;
|
||||
import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes;
|
||||
import static org.graalvm.compiler.nodes.NamedLocationIdentity.FINAL_LOCATION;
|
||||
|
||||
@ -32,9 +31,11 @@ import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
import org.graalvm.compiler.core.common.type.TypeReference;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.nodes.CompressionNode;
|
||||
import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp;
|
||||
import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp;
|
||||
import org.graalvm.compiler.hotspot.replacements.HubGetClassNode;
|
||||
import org.graalvm.compiler.nodes.ConstantNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
@ -67,12 +68,10 @@ import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
*/
|
||||
public class LoadJavaMirrorWithKlassPhase extends BasePhase<PhaseContext> {
|
||||
|
||||
private final int classMirrorOffset;
|
||||
private final CompressEncoding oopEncoding;
|
||||
|
||||
public LoadJavaMirrorWithKlassPhase(int classMirrorOffset, CompressEncoding oopEncoding) {
|
||||
this.classMirrorOffset = classMirrorOffset;
|
||||
this.oopEncoding = oopEncoding;
|
||||
public LoadJavaMirrorWithKlassPhase(GraalHotSpotVMConfig config) {
|
||||
this.oopEncoding = config.useCompressedOops ? config.getOopEncoding() : null;
|
||||
}
|
||||
|
||||
private ValueNode getClassConstantReplacement(StructuredGraph graph, PhaseContext context, JavaConstant constant) {
|
||||
@ -85,13 +84,12 @@ public class LoadJavaMirrorWithKlassPhase extends BasePhase<PhaseContext> {
|
||||
|
||||
if (type instanceof HotSpotResolvedObjectType) {
|
||||
ConstantNode klass = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) type).klass(), metaAccess, graph);
|
||||
AddressNode address = graph.unique(new OffsetAddressNode(klass, ConstantNode.forLong(classMirrorOffset, graph)));
|
||||
ValueNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, stamp));
|
||||
ValueNode getClass = graph.unique(new HubGetClassNode(metaAccess, klass));
|
||||
|
||||
if (((HotSpotObjectConstant) constant).isCompressed()) {
|
||||
return CompressionNode.compress(read, oopEncoding);
|
||||
return CompressionNode.compress(getClass, oopEncoding);
|
||||
} else {
|
||||
return read;
|
||||
return getClass;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
|
@ -94,7 +94,7 @@ public class OnStackReplacementPhase extends Phase {
|
||||
assert graph.getNodes(EntryMarkerNode.TYPE).isEmpty();
|
||||
return;
|
||||
}
|
||||
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement initial at bci %d", graph.getEntryBCI());
|
||||
Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement initial at bci %d", graph.getEntryBCI());
|
||||
|
||||
EntryMarkerNode osr;
|
||||
int maxIterations = -1;
|
||||
@ -144,7 +144,7 @@ public class OnStackReplacementPhase extends Phase {
|
||||
proxy.replaceAndDelete(proxy.value());
|
||||
}
|
||||
GraphUtil.removeFixedWithUnusedInputs(osr);
|
||||
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement loop peeling result");
|
||||
Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement loop peeling result");
|
||||
} while (true);
|
||||
|
||||
FrameState osrState = osr.stateAfter();
|
||||
@ -157,7 +157,7 @@ public class OnStackReplacementPhase extends Phase {
|
||||
graph.setStart(osrStart);
|
||||
osrStart.setStateAfter(osrState);
|
||||
|
||||
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement after setting OSR start");
|
||||
Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement after setting OSR start");
|
||||
final int localsSize = osrState.localsSize();
|
||||
final int locksSize = osrState.locksSize();
|
||||
|
||||
@ -188,9 +188,9 @@ public class OnStackReplacementPhase extends Phase {
|
||||
}
|
||||
|
||||
osr.replaceAtUsages(InputType.Guard, osrStart);
|
||||
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement after replacing entry proxies");
|
||||
Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement after replacing entry proxies");
|
||||
GraphUtil.killCFG(start);
|
||||
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement result");
|
||||
Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement result");
|
||||
new DeadCodeEliminationPhase(Required).apply(graph);
|
||||
|
||||
if (currentOSRWithLocks) {
|
||||
@ -210,7 +210,7 @@ public class OnStackReplacementPhase extends Phase {
|
||||
osrMonitorEnter.setNext(oldNext);
|
||||
osrStart.setNext(osrMonitorEnter);
|
||||
}
|
||||
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "After inserting OSR monitor enters");
|
||||
Debug.dump(Debug.DETAILED_LEVEL, graph, "After inserting OSR monitor enters");
|
||||
/*
|
||||
* Ensure balanced monitorenter - monitorexit
|
||||
*
|
||||
@ -226,7 +226,7 @@ public class OnStackReplacementPhase extends Phase {
|
||||
}
|
||||
}
|
||||
}
|
||||
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement result");
|
||||
Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement result");
|
||||
new DeadCodeEliminationPhase(Required).apply(graph);
|
||||
/*
|
||||
* There must not be any parameter nodes left after OSR compilation.
|
||||
|
@ -28,9 +28,6 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||
import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
|
||||
@ -43,6 +40,9 @@ import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
|
||||
import org.graalvm.compiler.phases.BasePhase;
|
||||
import org.graalvm.compiler.phases.tiers.PhaseContext;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
||||
import jdk.vm.ci.meta.Constant;
|
||||
|
||||
public class EliminateRedundantInitializationPhase extends BasePhase<PhaseContext> {
|
||||
/**
|
||||
* Find blocks with class initializing nodes for the class identified the by the constant node.
|
||||
@ -204,7 +204,7 @@ public class EliminateRedundantInitializationPhase extends BasePhase<PhaseContex
|
||||
ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, true, false);
|
||||
ArrayList<Node> redundantInits = new ArrayList<>();
|
||||
for (ConstantNode node : getConstantNodes(graph)) {
|
||||
JavaConstant constant = node.asJavaConstant();
|
||||
Constant constant = node.asConstant();
|
||||
if (constant instanceof HotSpotMetaspaceConstant) {
|
||||
redundantInits.addAll(processConstantNode(cfg, node));
|
||||
}
|
||||
|
@ -25,8 +25,11 @@ package org.graalvm.compiler.hotspot.replacements;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
|
||||
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import org.graalvm.compiler.core.common.LocationIdentity;
|
||||
import org.graalvm.compiler.core.common.calc.Condition;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.graph.spi.Canonicalizable;
|
||||
@ -42,6 +45,7 @@ import org.graalvm.compiler.nodes.calc.FloatingNode;
|
||||
import org.graalvm.compiler.nodes.extended.GetClassNode;
|
||||
import org.graalvm.compiler.nodes.extended.GuardingNode;
|
||||
import org.graalvm.compiler.nodes.extended.LoadHubNode;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
|
||||
import org.graalvm.compiler.nodes.memory.ReadNode;
|
||||
import org.graalvm.compiler.nodes.memory.address.AddressNode;
|
||||
import org.graalvm.compiler.nodes.spi.Lowerable;
|
||||
@ -69,19 +73,30 @@ public final class ClassGetHubNode extends FloatingNode implements Lowerable, Ca
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node canonical(CanonicalizerTool tool) {
|
||||
if (tool.allUsagesAvailable() && hasNoUsages()) {
|
||||
public static ValueNode create(ValueNode clazz, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean allUsagesAvailable) {
|
||||
return canonical(null, metaAccess, constantReflection, allUsagesAvailable, KlassPointerStamp.klass(), clazz);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode clazz) {
|
||||
ValueNode clazzValue = create(clazz, b.getMetaAccess(), b.getConstantReflection(), false);
|
||||
b.push(JavaKind.Object, b.recursiveAppend(clazzValue));
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ValueNode canonical(ClassGetHubNode classGetHubNode, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean allUsagesAvailable, Stamp stamp,
|
||||
ValueNode clazz) {
|
||||
ClassGetHubNode self = classGetHubNode;
|
||||
if (allUsagesAvailable && self != null && self.hasNoUsages()) {
|
||||
return null;
|
||||
} else {
|
||||
if (clazz.isConstant()) {
|
||||
MetaAccessProvider metaAccess = tool.getMetaAccess();
|
||||
if (metaAccess != null) {
|
||||
ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(clazz.asJavaConstant());
|
||||
ResolvedJavaType exactType = constantReflection.asJavaType(clazz.asJavaConstant());
|
||||
if (exactType.isPrimitive()) {
|
||||
return ConstantNode.forConstant(stamp(), JavaConstant.NULL_POINTER, metaAccess);
|
||||
return ConstantNode.forConstant(stamp, JavaConstant.NULL_POINTER, metaAccess);
|
||||
} else {
|
||||
return ConstantNode.forConstant(stamp(), tool.getConstantReflection().asObjectHub(exactType), metaAccess);
|
||||
return ConstantNode.forConstant(stamp, constantReflection.asObjectHub(exactType), metaAccess);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -90,11 +105,19 @@ public final class ClassGetHubNode extends FloatingNode implements Lowerable, Ca
|
||||
return new LoadHubNode(KlassPointerStamp.klassNonNull(), getClass.getObject());
|
||||
}
|
||||
if (clazz instanceof HubGetClassNode) {
|
||||
// replace _klass._java_mirror._klass -> _klass
|
||||
// Replace: _klass._java_mirror._klass -> _klass
|
||||
return ((HubGetClassNode) clazz).getHub();
|
||||
}
|
||||
return this;
|
||||
if (self == null) {
|
||||
self = new ClassGetHubNode(clazz);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node canonical(CanonicalizerTool tool) {
|
||||
return canonical(this, tool.getMetaAccess(), tool.getConstantReflection(), tool.allUsagesAvailable(), stamp(), clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -702,17 +702,17 @@ public class HotSpotReplacementsUtil {
|
||||
|
||||
public static Word loadWordFromObject(Object object, int offset) {
|
||||
ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
|
||||
return loadWordFromObjectIntrinsic(object, offset, getWordKind(), LocationIdentity.any());
|
||||
return loadWordFromObjectIntrinsic(object, offset, LocationIdentity.any(), getWordKind());
|
||||
}
|
||||
|
||||
public static Word loadWordFromObject(Object object, int offset, LocationIdentity identity) {
|
||||
ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
|
||||
return loadWordFromObjectIntrinsic(object, offset, getWordKind(), identity);
|
||||
return loadWordFromObjectIntrinsic(object, offset, identity, getWordKind());
|
||||
}
|
||||
|
||||
public static KlassPointer loadKlassFromObject(Object object, int offset, LocationIdentity identity) {
|
||||
ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
|
||||
return loadKlassFromObjectIntrinsic(object, offset, getWordKind(), identity);
|
||||
return loadKlassFromObjectIntrinsic(object, offset, identity, getWordKind());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -725,17 +725,17 @@ public class HotSpotReplacementsUtil {
|
||||
return registerAsWord(register, true, false);
|
||||
}
|
||||
|
||||
@NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true)
|
||||
@NodeIntrinsic(value = ReadRegisterNode.class)
|
||||
public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming);
|
||||
|
||||
@NodeIntrinsic(value = WriteRegisterNode.class, setStampFromReturnType = true)
|
||||
@NodeIntrinsic(value = WriteRegisterNode.class)
|
||||
public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value);
|
||||
|
||||
@NodeIntrinsic(value = RawLoadNode.class, setStampFromReturnType = true)
|
||||
private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity);
|
||||
@NodeIntrinsic(value = RawLoadNode.class)
|
||||
private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter JavaKind wordKind);
|
||||
|
||||
@NodeIntrinsic(value = RawLoadNode.class, setStampFromReturnType = true)
|
||||
private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity);
|
||||
@NodeIntrinsic(value = RawLoadNode.class)
|
||||
private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter JavaKind wordKind);
|
||||
|
||||
@NodeIntrinsic(value = LoadHubNode.class)
|
||||
public static native KlassPointer loadHubIntrinsic(Object object);
|
||||
@ -803,6 +803,8 @@ public class HotSpotReplacementsUtil {
|
||||
|
||||
public static final LocationIdentity CLASS_MIRROR_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror");
|
||||
|
||||
public static final LocationIdentity CLASS_MIRROR_HANDLE_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror handle");
|
||||
|
||||
public static final LocationIdentity HEAP_TOP_LOCATION = NamedLocationIdentity.mutable("HeapTop");
|
||||
|
||||
@Fold
|
||||
|
@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot.replacements;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
|
||||
|
||||
import org.graalvm.compiler.core.common.GraalOptions;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
import org.graalvm.compiler.core.common.type.TypeReference;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
@ -70,7 +71,7 @@ public final class HubGetClassNode extends FloatingNode implements Lowerable, Ca
|
||||
return null;
|
||||
} else {
|
||||
MetaAccessProvider metaAccess = tool.getMetaAccess();
|
||||
if (metaAccess != null && hub.isConstant()) {
|
||||
if (metaAccess != null && hub.isConstant() && !GraalOptions.ImmutableCode.getValue(graph().getOptions())) {
|
||||
ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(hub.asConstant());
|
||||
if (exactType != null) {
|
||||
return ConstantNode.forConstant(tool.getConstantReflection().asJavaClass(exactType), metaAccess);
|
||||
|
@ -25,6 +25,9 @@ package org.graalvm.compiler.hotspot.replacements;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
|
||||
|
||||
import jdk.vm.ci.meta.ConstantReflectionProvider;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import org.graalvm.compiler.core.common.type.ObjectStamp;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
@ -38,6 +41,7 @@ import org.graalvm.compiler.nodes.ConstantNode;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.calc.FloatingNode;
|
||||
import org.graalvm.compiler.nodes.extended.LoadHubNode;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
|
||||
import org.graalvm.compiler.nodes.spi.Lowerable;
|
||||
import org.graalvm.compiler.nodes.spi.LoweringTool;
|
||||
|
||||
@ -63,6 +67,18 @@ public final class KlassLayoutHelperNode extends FloatingNode implements Canonic
|
||||
this.klass = klass;
|
||||
}
|
||||
|
||||
public static ValueNode create(GraalHotSpotVMConfig config, ValueNode klass, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess) {
|
||||
Stamp stamp = StampFactory.forKind(JavaKind.Int);
|
||||
return canonical(null, config, klass, stamp, constantReflection, metaAccess);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, @InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass) {
|
||||
ValueNode valueNode = create(config, klass, b.getConstantReflection(), b.getMetaAccess());
|
||||
b.push(JavaKind.Int, b.recursiveAppend(valueNode));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean inferStamp() {
|
||||
if (klass instanceof LoadHubNode) {
|
||||
@ -92,10 +108,17 @@ public final class KlassLayoutHelperNode extends FloatingNode implements Canonic
|
||||
if (tool.allUsagesAvailable() && hasNoUsages()) {
|
||||
return null;
|
||||
} else {
|
||||
return canonical(this, config, klass, stamp(), tool.getConstantReflection(), tool.getMetaAccess());
|
||||
}
|
||||
}
|
||||
|
||||
private static ValueNode canonical(KlassLayoutHelperNode klassLayoutHelperNode, GraalHotSpotVMConfig config, ValueNode klass, Stamp stamp, ConstantReflectionProvider constantReflection,
|
||||
MetaAccessProvider metaAccess) {
|
||||
KlassLayoutHelperNode self = klassLayoutHelperNode;
|
||||
if (klass.isConstant()) {
|
||||
if (!klass.asConstant().isDefaultForKind()) {
|
||||
Constant constant = stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), klass.asConstant(), config.klassLayoutHelperOffset);
|
||||
return ConstantNode.forConstant(stamp(), constant, tool.getMetaAccess());
|
||||
Constant constant = stamp.readConstant(constantReflection.getMemoryAccessProvider(), klass.asConstant(), config.klassLayoutHelperOffset);
|
||||
return ConstantNode.forConstant(stamp, constant, metaAccess);
|
||||
}
|
||||
}
|
||||
if (klass instanceof LoadHubNode) {
|
||||
@ -106,13 +129,15 @@ public final class KlassLayoutHelperNode extends FloatingNode implements Canonic
|
||||
HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) ostamp.type();
|
||||
if (type != null && type.isArray() && !type.getComponentType().isPrimitive()) {
|
||||
// The layout for all object arrays is the same.
|
||||
Constant constant = stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), type.klass(), config.klassLayoutHelperOffset);
|
||||
return ConstantNode.forConstant(stamp(), constant, tool.getMetaAccess());
|
||||
Constant constant = stamp.readConstant(constantReflection.getMemoryAccessProvider(), type.klass(), config.klassLayoutHelperOffset);
|
||||
return ConstantNode.forConstant(stamp, constant, metaAccess);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
if (self == null) {
|
||||
self = new KlassLayoutHelperNode(config, klass);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,8 +35,10 @@ import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER
|
||||
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
|
||||
import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
|
||||
import org.graalvm.compiler.nodes.java.LoadExceptionObjectNode;
|
||||
@ -52,6 +54,7 @@ import org.graalvm.compiler.word.Word;
|
||||
import jdk.vm.ci.code.BytecodeFrame;
|
||||
import jdk.vm.ci.code.Register;
|
||||
import jdk.vm.ci.code.TargetDescription;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
|
||||
/**
|
||||
* Snippet for loading the exception object at the start of an exception dispatcher.
|
||||
@ -76,15 +79,19 @@ public class LoadExceptionObjectSnippets implements Snippets {
|
||||
public static class Templates extends AbstractTemplates {
|
||||
|
||||
private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException", EXCEPTION_OOP_LOCATION, EXCEPTION_PC_LOCATION);
|
||||
private final HotSpotWordTypes wordTypes;
|
||||
|
||||
public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) {
|
||||
super(options, providers, providers.getSnippetReflection(), target);
|
||||
this.wordTypes = providers.getWordTypes();
|
||||
}
|
||||
|
||||
public void lower(LoadExceptionObjectNode loadExceptionObject, HotSpotRegistersProvider registers, LoweringTool tool) {
|
||||
StructuredGraph graph = loadExceptionObject.graph();
|
||||
if (LoadExceptionObjectInVM.getValue(graph.getOptions())) {
|
||||
ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), true, false));
|
||||
ResolvedJavaType wordType = providers.getMetaAccess().lookupJavaType(Word.class);
|
||||
Stamp stamp = wordTypes.getWordStamp(wordType);
|
||||
ReadRegisterNode thread = graph.add(new ReadRegisterNode(stamp, registers.getThreadRegister(), true, false));
|
||||
graph.addBeforeFixed(loadExceptionObject, thread);
|
||||
ForeignCallNode loadExceptionC = graph.add(new ForeignCallNode(providers.getForeignCalls(), LOAD_AND_CLEAR_EXCEPTION, thread));
|
||||
loadExceptionC.setStateAfter(loadExceptionObject.stateAfter());
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user