--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java Thu Apr 06 23:01:27 2017 +0000
@@ -54,12 +54,9 @@
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 @@
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 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);
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java Thu Apr 06 23:01:27 2017 +0000
@@ -145,7 +145,7 @@
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() {
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java Thu Apr 06 23:01:27 2017 +0000
@@ -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 @@
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 HotSpotCompiledCode compiledCode(CompilationResult result) {
- return HotSpotCompiledCodeBuilder.createCompiledCode(method, null, result);
+ return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), method, null, result);
}
}
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java Thu Apr 06 23:01:27 2017 +0000
@@ -49,7 +49,7 @@
}
public HotSpotCompiledCode compiledCode(CompilationResult result) {
- return HotSpotCompiledCodeBuilder.createCompiledCode(null, null, result);
+ return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), null, null, result);
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -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 @@
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();
+ }
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java Thu Apr 06 23:01:27 2017 +0000
@@ -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 @@
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);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceStatisticsPrinter.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceStatisticsPrinter.java Thu Apr 06 23:01:27 2017 +0000
@@ -35,7 +35,7 @@
@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 @@
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 @@
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) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java Thu Apr 06 23:01:27 2017 +0000
@@ -343,116 +343,7 @@
if (lt instanceof PrimitiveConstant) {
PrimitiveConstant lp = (PrimitiveConstant) lt;
PrimitiveConstant rp = (PrimitiveConstant) rt;
- switch (lp.getJavaKind()) {
- case Boolean:
- case Byte:
- case Char:
- case Short:
- case Int: {
- int x = lp.asInt();
- int y = rp.asInt();
- switch (this) {
- case EQ:
- return x == y;
- case NE:
- return x != y;
- case LT:
- return x < y;
- case LE:
- return x <= y;
- case GT:
- return x > y;
- case GE:
- return x >= y;
- case AE:
- return UnsignedMath.aboveOrEqual(x, y);
- case BE:
- return UnsignedMath.belowOrEqual(x, y);
- case AT:
- return UnsignedMath.aboveThan(x, y);
- case BT:
- return UnsignedMath.belowThan(x, y);
- default:
- throw new GraalError("expected condition: %s", this);
- }
- }
- case Long: {
- long x = lp.asLong();
- long y = rp.asLong();
- switch (this) {
- case EQ:
- return x == y;
- case NE:
- return x != y;
- case LT:
- return x < y;
- case LE:
- return x <= y;
- case GT:
- return x > y;
- case GE:
- return x >= y;
- case AE:
- return UnsignedMath.aboveOrEqual(x, y);
- case BE:
- return UnsignedMath.belowOrEqual(x, y);
- case AT:
- return UnsignedMath.aboveThan(x, y);
- case BT:
- return UnsignedMath.belowThan(x, y);
- default:
- throw new GraalError("expected condition: %s", this);
- }
- }
- case Float: {
- float x = lp.asFloat();
- float y = rp.asFloat();
- if (Float.isNaN(x) || Float.isNaN(y)) {
- return unorderedIsTrue;
- }
- switch (this) {
- case EQ:
- return x == y;
- case NE:
- return x != y;
- case LT:
- return x < y;
- case LE:
- return x <= y;
- case GT:
- return x > y;
- case GE:
- return x >= y;
- default:
- throw new GraalError("expected condition: %s", this);
- }
- }
- case Double: {
- double x = lp.asDouble();
- double y = rp.asDouble();
- if (Double.isNaN(x) || Double.isNaN(y)) {
- return unorderedIsTrue;
- }
- switch (this) {
- case EQ:
- return x == y;
- case NE:
- return x != y;
- case LT:
- return x < y;
- case LE:
- return x <= y;
- case GT:
- return x > y;
- case GE:
- return x >= y;
- default:
- throw new GraalError("expected condition: %s", this);
- }
- }
- default:
- throw new GraalError("expected value kind %s while folding condition: %s", lp.getJavaKind(), this);
- }
+ return foldCondition(lp, rp, unorderedIsTrue);
} else {
Boolean equal = constantReflection.constantEquals(lt, rt);
if (equal == null) {
@@ -469,6 +360,128 @@
}
}
+ /**
+ * 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:
+ case Char:
+ case Short:
+ case Int: {
+ int x = lp.asInt();
+ int y = rp.asInt();
+ switch (this) {
+ case EQ:
+ return x == y;
+ case NE:
+ return x != y;
+ case LT:
+ return x < y;
+ case LE:
+ return x <= y;
+ case GT:
+ return x > y;
+ case GE:
+ return x >= y;
+ case AE:
+ return UnsignedMath.aboveOrEqual(x, y);
+ case BE:
+ return UnsignedMath.belowOrEqual(x, y);
+ case AT:
+ return UnsignedMath.aboveThan(x, y);
+ case BT:
+ return UnsignedMath.belowThan(x, y);
+ default:
+ throw new GraalError("expected condition: %s", this);
+ }
+ }
+ case Long: {
+ long x = lp.asLong();
+ long y = rp.asLong();
+ switch (this) {
+ case EQ:
+ return x == y;
+ case NE:
+ return x != y;
+ case LT:
+ return x < y;
+ case LE:
+ return x <= y;
+ case GT:
+ return x > y;
+ case GE:
+ return x >= y;
+ case AE:
+ return UnsignedMath.aboveOrEqual(x, y);
+ case BE:
+ return UnsignedMath.belowOrEqual(x, y);
+ case AT:
+ return UnsignedMath.aboveThan(x, y);
+ case BT:
+ return UnsignedMath.belowThan(x, y);
+ default:
+ throw new GraalError("expected condition: %s", this);
+ }
+ }
+ case Float: {
+ float x = lp.asFloat();
+ float y = rp.asFloat();
+ if (Float.isNaN(x) || Float.isNaN(y)) {
+ return unorderedIsTrue;
+ }
+ switch (this) {
+ case EQ:
+ return x == y;
+ case NE:
+ return x != y;
+ case LT:
+ return x < y;
+ case LE:
+ return x <= y;
+ case GT:
+ return x > y;
+ case GE:
+ return x >= y;
+ default:
+ throw new GraalError("expected condition: %s", this);
+ }
+ }
+ case Double: {
+ double x = lp.asDouble();
+ double y = rp.asDouble();
+ if (Double.isNaN(x) || Double.isNaN(y)) {
+ return unorderedIsTrue;
+ }
+ switch (this) {
+ case EQ:
+ return x == y;
+ case NE:
+ return x != y;
+ case LT:
+ return x < y;
+ case LE:
+ return x <= y;
+ case GT:
+ return x > y;
+ case GE:
+ return x >= y;
+ default:
+ throw new GraalError("expected condition: %s", this);
+ }
+ }
+ default:
+ throw new GraalError("expected value kind %s while folding condition: %s", lp.getJavaKind(), this);
+ }
+ }
+
public Condition join(Condition other) {
if (other == this) {
return this;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java Thu Apr 06 23:01:27 2017 +0000
@@ -154,6 +154,7 @@
return Double.isNaN(lowerBound);
}
+ @Override
public boolean isUnrestricted() {
return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN;
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java Thu Apr 06 23:01:27 2017 +0000
@@ -59,6 +59,11 @@
}
@Override
+ public boolean isUnrestricted() {
+ return true;
+ }
+
+ @Override
public Stamp empty() {
return this;
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java Thu Apr 06 23:01:27 2017 +0000
@@ -254,6 +254,7 @@
return upMask;
}
+ @Override
public boolean isUnrestricted() {
return lowerBound == CodeUtil.minValue(getBits()) && upperBound == CodeUtil.maxValue(getBits()) && downMask == 0 && upMask == CodeUtil.mask(getBits());
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java Thu Apr 06 23:01:27 2017 +0000
@@ -126,6 +126,13 @@
}
/**
+ * 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.
*
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java Thu Apr 06 23:01:27 2017 +0000
@@ -39,33 +39,6 @@
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 @@
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);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java Thu Apr 06 23:01:27 2017 +0000
@@ -46,6 +46,11 @@
}
@Override
+ public boolean isUnrestricted() {
+ return true;
+ }
+
+ @Override
public JavaKind getStackKind() {
return JavaKind.Void;
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java Thu Apr 06 23:01:27 2017 +0000
@@ -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 @@
}
}
- 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 @@
* 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 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;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java Thu Apr 06 23:01:27 2017 +0000
@@ -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 @@
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 @@
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;
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java Thu Apr 06 23:01:27 2017 +0000
@@ -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 @@
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 @@
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)) {
@@ -261,6 +261,13 @@
}
@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
SPARCKind cmpSPARCKind = (SPARCKind) cmpKind;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -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.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 @@
sum0 = a;
} else {
int sum = a;
- for (int i = 0; i < n; i++) {
+ for (int i = 1; i < n; i++) {
sum += i;
}
sum0 = sum;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest3.java Thu Apr 06 23:01:27 2017 +0000
@@ -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);
+ }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -32,8 +32,8 @@
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 static void snippet02(int a) {
if (a == 0) {
- if (a * 3 != 0) {
+ if (a * 11 != 0) {
shouldBeOptimizedAway();
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest1.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest1.java Thu Apr 06 23:01:27 2017 +0000
@@ -22,25 +22,25 @@
*/
package org.graalvm.compiler.core.test;
+import org.graalvm.compiler.api.directives.GraalDirectives;
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 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 @@
}
@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 @@
}
@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 @@
}
@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 @@
if (a > -2) {
if (a > -3) {
if (a == 1) {
- return 42;
+ sink2 = 42;
} else {
- return 1;
+ sink1 = 1;
}
}
}
@@ -112,18 +112,18 @@
}
}
}
- 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 @@
}
@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
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java Thu Apr 06 23:01:27 2017 +0000
@@ -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) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java Thu Apr 06 23:01:27 2017 +0000
@@ -34,13 +34,6 @@
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 @@
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);
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java Thu Apr 06 23:01:27 2017 +0000
@@ -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 @@
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 @@
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 @@
}
@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 @@
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 @@
if (!(a instanceof B)) {
GraalDirectives.deoptimizeAndInvalidate();
}
- return 1;
+ sink1 = 1;
}
@Test
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Thu Apr 06 23:01:27 2017 +0000
@@ -42,15 +42,9 @@
* 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 @@
@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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DeMorganCanonicalizationTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -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);
+ }
+
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -86,9 +86,9 @@
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);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueDefaultMethodTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueDefaultMethodTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -142,7 +142,7 @@
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);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -82,7 +82,7 @@
}
}
- Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After lowering");
+ Debug.dump(Debug.BASIC_LEVEL, graph, "After lowering");
Assert.assertNotNull(returnNode);
Assert.assertNotNull(monitorexit);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -78,6 +78,7 @@
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.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.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.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 @@
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 @@
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 @@
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 @@
}
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 @@
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));
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -217,7 +217,7 @@
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);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -25,7 +25,8 @@
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 @@
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);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -717,7 +717,7 @@
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);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -61,7 +61,7 @@
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());
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -142,7 +142,7 @@
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 @@
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) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -58,9 +58,11 @@
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 @@
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
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PhiCreationTests.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PhiCreationTests.java Thu Apr 06 23:01:27 2017 +0000
@@ -70,7 +70,7 @@
@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 @@
@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());
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -59,7 +59,7 @@
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);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -94,7 +94,7 @@
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
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -131,7 +131,7 @@
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);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java Thu Apr 06 23:01:27 2017 +0000
@@ -69,7 +69,7 @@
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();
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -41,7 +41,7 @@
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
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -88,7 +88,7 @@
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);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -180,7 +180,7 @@
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 @@
@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 @@
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());
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -83,9 +83,28 @@
@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 @@
@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 @@
@Override
protected void run(StructuredGraph graph) {
- Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "%s", graph);
+ Debug.dump(Debug.BASIC_LEVEL, graph, "%s", graph);
}
}
@@ -234,6 +253,16 @@
}
@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);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -135,6 +135,7 @@
}
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};
@@ -144,6 +145,18 @@
}
@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() {
testPartialEscapeAnalysis("testCacheSnippet", 0.75, 1);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -244,10 +244,10 @@
? 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;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -121,7 +121,7 @@
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 @@
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;
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/GraalTutorial.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/GraalTutorial.java Thu Apr 06 23:01:27 2017 +0000
@@ -25,6 +25,8 @@
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 @@
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());
+ }
}
/*
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java Thu Apr 06 23:01:27 2017 +0000
@@ -39,6 +39,7 @@
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,11 +176,43 @@
} 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.
*/
@SuppressWarnings("try")
@@ -190,21 +223,25 @@
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 @@
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 @@
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 @@
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");
}
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java Thu Apr 06 23:01:27 2017 +0000
@@ -46,6 +46,8 @@
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
-
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -91,12 +91,12 @@
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);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java Thu Apr 06 23:01:27 2017 +0000
@@ -122,11 +122,41 @@
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 static boolean isLogEnabled() {
- return isLogEnabled(BASIC_LOG_LEVEL);
+ return isLogEnabled(BASIC_LEVEL);
}
public static boolean isLogEnabled(int logLevel) {
@@ -420,7 +450,7 @@
}
public static void log(String msg) {
- log(BASIC_LOG_LEVEL, msg);
+ log(BASIC_LEVEL, msg);
}
/**
@@ -435,7 +465,7 @@
}
public static void log(String format, Object arg) {
- log(BASIC_LOG_LEVEL, format, arg);
+ log(BASIC_LEVEL, format, arg);
}
/**
@@ -451,7 +481,7 @@
}
public static void log(String format, int arg) {
- log(BASIC_LOG_LEVEL, format, arg);
+ log(BASIC_LEVEL, format, arg);
}
/**
@@ -467,7 +497,7 @@
}
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 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 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 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 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 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 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 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 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 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 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 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 static void logv(String format, Object... args) {
- logv(BASIC_LOG_LEVEL, format, args);
+ logv(BASIC_LEVEL, format, args);
}
/**
@@ -655,7 +685,7 @@
@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 @@
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 static Indent logAndIndent(String msg) {
- return logAndIndent(BASIC_LOG_LEVEL, msg);
+ return logAndIndent(BASIC_LEVEL, msg);
}
/**
@@ -789,7 +827,7 @@
}
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 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 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 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 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 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 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 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 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 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 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 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 @@
@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);
}
/**
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugFilter.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugFilter.java Thu Apr 06 23:01:27 2017 +0000
@@ -41,28 +41,28 @@
* 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 @@
* 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 @@
level = 0;
} else {
pattern = t;
- level = Debug.BASIC_LOG_LEVEL;
+ level = Debug.BASIC_LEVEL;
}
} else {
pattern = t.substring(0, idx);
@@ -119,13 +119,13 @@
} 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 @@
}
} else {
- level = Debug.BASIC_LOG_LEVEL;
+ level = Debug.BASIC_LEVEL;
}
}
@@ -147,7 +147,7 @@
*/
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) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugRetryableTask.java Thu Apr 06 23:01:27 2017 +0000
@@ -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;
+ }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java Thu Apr 06 23:01:27 2017 +0000
@@ -79,7 +79,9 @@
@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 @@
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 @@
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);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java Thu Apr 06 23:01:27 2017 +0000
@@ -352,7 +352,7 @@
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");
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Thu Apr 06 23:01:27 2017 +0000
@@ -405,6 +405,13 @@
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;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java Thu Apr 06 23:01:27 2017 +0000
@@ -40,6 +40,8 @@
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 @@
* 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 @@
/**
* 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 @@
* @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 @@
if (usage1 == null) {
return 1;
}
- return 2 + extraUsagesCount;
+ return INLINE_USAGE_COUNT + extraUsagesCount;
}
/**
@@ -391,30 +400,45 @@
}
private void movUsageFromEndTo(int destIndex) {
- int lastIndex = this.getUsageCount() - 1;
- if (destIndex == 0) {
- if (lastIndex == 0) {
- usage0 = null;
- return;
- } else if (lastIndex == 1) {
- usage0 = usage1;
- usage1 = null;
- return;
- } else {
- usage0 = extraUsages[lastIndex - INLINE_USAGE_COUNT];
- }
+ if (destIndex >= INLINE_USAGE_COUNT) {
+ movUsageFromEndToExtraUsages(destIndex - INLINE_USAGE_COUNT);
} else if (destIndex == 1) {
- if (lastIndex == 1) {
- usage1 = null;
- return;
- }
- usage1 = extraUsages[lastIndex - INLINE_USAGE_COUNT];
+ movUsageFromEndToIndexOne();
} else {
- Node n = extraUsages[lastIndex - INLINE_USAGE_COUNT];
- extraUsages[destIndex - INLINE_USAGE_COUNT] = n;
+ assert destIndex == 0;
+ movUsageFromEndToIndexZero();
}
- extraUsages[lastIndex - INLINE_USAGE_COUNT] = null;
+ }
+
+ 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;
+ } else {
+ usage0 = 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 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 @@
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 final void replaceAtUsages(Node other) {
- replaceAtUsages(other, null, null);
+ replaceAtAllUsages(other, (Node) null);
}
public final void replaceAtUsages(Node other, Predicate<Node> filter) {
@@ -606,22 +632,60 @@
}
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);
+ 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);
+ /*
+ * Don't notify for nodes which are about to be deleted.
+ */
+ if (toBeDeleted == null || usage != toBeDeleted) {
+ maybeNotifyInputChanged(usage);
+ }
+ 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)) {
- boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other);
- assert assertTrue(result, "not found in inputs, usage: %s", usage);
- /*
- * Don't notify for nodes which are about to be deleted.
- */
- if (toBeDeleted == null || usage != toBeDeleted) {
- maybeNotifyInputChanged(usage);
- }
- if (other != null) {
- other.addUsage(usage);
- }
+ replaceAtUsage(other, toBeDeleted, usage);
this.movUsageFromEndTo(i);
} else {
++i;
@@ -641,21 +705,7 @@
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) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java Thu Apr 06 23:01:27 2017 +0000
@@ -154,7 +154,7 @@
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 @@
}
}
- 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 {
- forward();
- }
+ Node result = graph.getNode(nextNodeId);
+ forward();
+ return result;
}
@Override
@@ -230,7 +233,7 @@
@Override
public Iterator<Node> iterator() {
- return new MarkedNodeIterator(NodeBitMap.this, graph().getNodes().iterator());
+ return new MarkedNodeIterator();
}
public NodeBitMap copy() {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java Thu Apr 06 23:01:27 2017 +0000
@@ -599,23 +599,24 @@
}
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 @@
}
}
+ 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) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java Thu Apr 06 23:01:27 2017 +0000
@@ -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() {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java Thu Apr 06 23:01:27 2017 +0000
@@ -27,7 +27,7 @@
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 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) {
- long limit = (long) iterationLimitPerNode * graph.getNodeCount();
- iterationLimit = (int) Long.min(Integer.MAX_VALUE, limit);
- hardLimit = false;
- } else {
- iterationLimit = HARD_ITERATION_LIMIT;
- hardLimit = true;
- }
+ assert iterationLimitPerNode > 0;
+ long limit = (long) iterationLimitPerNode * graph.getNodeCount();
+ iterationLimit = (int) Long.min(Integer.MAX_VALUE, limit);
}
@Override
@@ -101,11 +94,8 @@
public boolean hasNext() {
dropDeleted();
if (iterationLimit <= 0) {
- if (hardLimit) {
- throw new PermanentBailoutException("Iteration limit reached");
- } else {
- return false;
- }
+ Debug.log(Debug.INFO_LEVEL, "Exceeded iteration limit in IterativeNodeWorkList");
+ return false;
}
return !worklist.isEmpty();
}
@@ -152,7 +142,7 @@
}
}
}
- assert checkInfiniteWork(node) : "Readded " + node;
+ assert checkInfiniteWork(node) : "Re-added " + node;
if (inQueue != null) {
inQueue.markAndGrow(node);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicate.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicate.java Thu Apr 06 23:01:27 2017 +0000
@@ -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);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java Thu Apr 06 23:01:27 2017 +0000
@@ -105,6 +105,7 @@
return !a.apply(n);
}
+ @Override
public NodePredicate negate() {
return a;
}
@@ -148,6 +149,7 @@
return this;
}
+ @Override
public NodePredicate negate() {
return new NegativeTypePredicate(this);
}
@@ -183,6 +185,7 @@
return this;
}
+ @Override
public NodePredicate negate() {
return new PositiveTypePredicate(this);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu Apr 06 23:01:27 2017 +0000
@@ -557,7 +557,7 @@
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");
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ClassSubstitutionsTests.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ClassSubstitutionsTests.java Thu Apr 06 23:01:27 2017 +0000
@@ -48,7 +48,7 @@
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);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -47,7 +47,7 @@
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;
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java Thu Apr 06 23:01:27 2017 +0000
@@ -57,7 +57,7 @@
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 @@
}
}
- /**
- * 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('.', '/');
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -53,6 +53,7 @@
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 @@
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)
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -58,7 +58,11 @@
@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 @@
@Test
public void testClassConstant() {
- test("classConstant");
+ test(getOptions(), "classConstant");
}
public static Class<?> primitiveClassConstant() {
@@ -86,7 +90,7 @@
@Test
public void testPrimitiveClassConstant() {
- test("primitiveClassConstant");
+ test(getOptions(), "primitiveClassConstant");
}
public static Wrapper compressedClassConstant(Wrapper w) {
@@ -97,7 +101,7 @@
@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 @@
@Test
public void testCompressedPrimitiveClassConstant() {
ArgSupplier arg = () -> new Wrapper();
- test("compressedPrimitiveClassConstant", arg);
+ test(getOptions(), "compressedPrimitiveClassConstant", arg);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/RetryableCompilationTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -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();
+ }
+ }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -266,7 +266,7 @@
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) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Thu Apr 06 23:01:27 2017 +0000
@@ -30,7 +30,20 @@
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.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.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 @@
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 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 @@
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 @@
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 @@
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 @@
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);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Thu Apr 06 23:01:27 2017 +0000
@@ -267,7 +267,31 @@
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");
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Thu Apr 06 23:01:27 2017 +0000
@@ -406,7 +406,7 @@
@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
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java Thu Apr 06 23:01:27 2017 +0000
@@ -42,6 +42,7 @@
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 @@
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 @@
* {@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,9 +215,11 @@
* can really be represented and recording the end PC seems to give the best results and
* corresponds with what C1 and C2 do.
*/
- for (SourceMapping source : target.getSourceMappings()) {
- sites.add(new Infopoint(source.getEndOffset(), new DebugInfo(source.getSourcePosition()), InfopointReason.BYTECODE_POSITION));
- assert verifySourcePositionReceivers(source.getSourcePosition());
+ 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();
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java Thu Apr 06 23:01:27 2017 +0000
@@ -71,8 +71,8 @@
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);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java Thu Apr 06 23:01:27 2017 +0000
@@ -24,6 +24,7 @@
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 @@
@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)) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java Thu Apr 06 23:01:27 2017 +0000
@@ -45,6 +45,7 @@
public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFactory {
private static MethodFilter[] graalCompileOnlyFilter;
+ private static boolean compileGraalWithC1Only;
private final HotSpotGraalJVMCIServiceLocator locator;
@@ -67,18 +68,17 @@
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)) {
- /*
- * 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.
- */
- adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization);
- adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple);
- }
+ 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.
+ */
+ 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 @@
@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
@@ -137,27 +134,15 @@
}
@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)) {
- // 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;
- }
+ 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,10 +178,12 @@
return CompilationLevel.Simple;
}
}
- 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")) {
- 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") || declaringClassName.startsWith("com.oracle.graal")) {
+ return CompilationLevel.Simple;
+ }
}
}
return level;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java Thu Apr 06 23:01:27 2017 +0000
@@ -30,68 +30,77 @@
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 {
- 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.
+ * 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 void addExports() {
- if (JAVA_SPECIFICATION_VERSION >= 9 && !exportsAdded) {
- Object javaBaseModule = getModule.invoke(String.class);
- Object graalModule = getModule.invoke(getClass());
- addExports.invokeStatic(javaBaseModule, "jdk.internal.misc", graalModule);
- addExports.invokeStatic(javaBaseModule, "jdk.internal.jimage", graalModule);
- addExports.invokeStatic(javaBaseModule, "com.sun.crypto.provider", graalModule);
- addOpens.invokeStatic(javaBaseModule, "jdk.internal.misc", graalModule);
- addOpens.invokeStatic(javaBaseModule, "jdk.internal.jimage", graalModule);
- addOpens.invokeStatic(javaBaseModule, "com.sun.crypto.provider", graalModule);
- exportsAdded = true;
+ 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.
+ */
+ private void addExports() {
+ if (JAVA_SPECIFICATION_VERSION >= 9 && !exportsAdded) {
+ Object javaBaseModule = getModule.invoke(String.class);
+ Object graalModule = getModule.invoke(getClass());
+ addExports.invokeStatic(javaBaseModule, "jdk.internal.misc", graalModule);
+ addExports.invokeStatic(javaBaseModule, "jdk.internal.jimage", graalModule);
+ addExports.invokeStatic(javaBaseModule, "com.sun.crypto.provider", graalModule);
+ addOpens.invokeStatic(javaBaseModule, "jdk.internal.misc", graalModule);
+ addOpens.invokeStatic(javaBaseModule, "jdk.internal.jimage", graalModule);
+ addOpens.invokeStatic(javaBaseModule, "com.sun.crypto.provider", graalModule);
+ exportsAdded = true;
+ }
+ }
+
+ <T> T getProvider(Class<T> service, HotSpotGraalJVMCIServiceLocator locator) {
+ if (service == JVMCICompilerFactory.class) {
+ addExports();
+ return service.cast(new HotSpotGraalCompilerFactory(locator));
+ } else if (service == HotSpotVMEventListener.class) {
+ if (graalRuntime != null) {
+ addExports();
+ return service.cast(new HotSpotGraalVMEventListener(graalRuntime));
+ }
+ }
+ return null;
+ }
+
+ private HotSpotGraalRuntime graalRuntime;
+
+ /**
+ * Notifies this object of the compiler created via {@link HotSpotGraalJVMCIServiceLocator}.
+ */
+ void onCompilerCreation(HotSpotGraalCompiler compiler) {
+ assert this.graalRuntime == null : "only expect a single JVMCICompiler to be created";
+ this.graalRuntime = (HotSpotGraalRuntime) compiler.getGraalRuntime();
}
}
- private HotSpotGraalRuntime graalRuntime;
-
@Override
public <T> T getProvider(Class<T> service) {
- if (service == JVMCICompilerFactory.class) {
- addExports();
- return service.cast(new HotSpotGraalCompilerFactory(this));
- } else if (service == HotSpotVMEventListener.class) {
- if (graalRuntime != null) {
- addExports();
- return service.cast(new HotSpotGraalVMEventListener(graalRuntime));
- }
- }
- return null;
+ return Shared.SINGLETON.getProvider(service, this);
}
/**
- * 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) {
- assert this.graalRuntime == null : "only expect a single JVMCICompiler to be created";
- this.graalRuntime = (HotSpotGraalRuntime) ((HotSpotGraalCompiler) compiler).getGraalRuntime();
+ @SuppressWarnings("static-method")
+ void onCompilerCreation(HotSpotGraalCompiler compiler) {
+ Shared.SINGLETON.onCompilerCreation(compiler);
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Thu Apr 06 23:01:27 2017 +0000
@@ -34,8 +34,22 @@
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 @@
}
private long runtimeStartTime;
+ private boolean shutdown;
/**
* Take action related to entering a new execution phase.
@@ -291,6 +306,7 @@
}
void shutdown() {
+ shutdown = true;
if (debugValuesPrinter != null) {
debugValuesPrinter.printDebugValues(options);
}
@@ -302,6 +318,8 @@
}
}
BenchmarkCounters.shutdown(runtime(), options, runtimeStartTime);
+
+ archiveAndDeleteOutputDirectory();
}
void clearMeters() {
@@ -321,4 +339,95 @@
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);
+ }
+ }
+ }
+ }
+ }
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java Thu Apr 06 23:01:27 2017 +0000
@@ -62,4 +62,19 @@
* 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();
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java Thu Apr 06 23:01:27 2017 +0000
@@ -46,10 +46,10 @@
@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));
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java Thu Apr 06 23:01:27 2017 +0000
@@ -45,7 +45,7 @@
}
/**
- * 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
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Thu Apr 06 23:01:27 2017 +0000
@@ -31,6 +31,7 @@
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 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 @@
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);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Thu Apr 06 23:01:27 2017 +0000
@@ -323,7 +323,8 @@
*/
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))));
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java Thu Apr 06 23:01:27 2017 +0000
@@ -90,7 +90,7 @@
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 @@
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
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java Thu Apr 06 23:01:27 2017 +0000
@@ -109,7 +109,7 @@
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 @@
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:
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -29,6 +29,7 @@
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 @@
* @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 @@
* @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 @@
@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() {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -32,7 +32,7 @@
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.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 @@
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;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -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 @@
@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 @@
return this;
}
- @NodeIntrinsic(setStampFromReturnType = true)
+ @NodeIntrinsic
public static native Word encode(Object constant);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -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.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 @@
*/
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 @@
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 {
/*
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -94,7 +94,7 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
}
}
}
- 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.
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -28,9 +28,6 @@
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.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 @@
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));
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -25,8 +25,11 @@
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.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 @@
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,14 +105,22 @@
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
public void lower(LoweringTool tool) {
tool.getLowerer().lower(this, tool);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Thu Apr 06 23:01:27 2017 +0000
@@ -702,17 +702,17 @@
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 @@
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 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
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -25,6 +25,7 @@
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 @@
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);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -25,6 +25,9 @@
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.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 @@
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,27 +108,36 @@
if (tool.allUsagesAvailable() && hasNoUsages()) {
return null;
} else {
- 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());
+ 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(constantReflection.getMemoryAccessProvider(), klass.asConstant(), config.klassLayoutHelperOffset);
+ return ConstantNode.forConstant(stamp, constant, metaAccess);
+ }
+ }
+ if (klass instanceof LoadHubNode) {
+ LoadHubNode hub = (LoadHubNode) klass;
+ Stamp hubStamp = hub.getValue().stamp();
+ if (hubStamp instanceof ObjectStamp) {
+ ObjectStamp ostamp = (ObjectStamp) hubStamp;
+ 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(constantReflection.getMemoryAccessProvider(), type.klass(), config.klassLayoutHelperOffset);
+ return ConstantNode.forConstant(stamp, constant, metaAccess);
}
}
- if (klass instanceof LoadHubNode) {
- LoadHubNode hub = (LoadHubNode) klass;
- Stamp hubStamp = hub.getValue().stamp();
- if (hubStamp instanceof ObjectStamp) {
- ObjectStamp ostamp = (ObjectStamp) hubStamp;
- 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());
- }
- }
- }
- return this;
}
+ if (self == null) {
+ self = new KlassLayoutHelperNode(config, klass);
+ }
+ return self;
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java Thu Apr 06 23:01:27 2017 +0000
@@ -35,8 +35,10 @@
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 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 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());
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Thu Apr 06 23:01:27 2017 +0000
@@ -56,7 +56,7 @@
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeTlabTop;
import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileAllocations;
import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileAllocationsContext;
-import static org.graalvm.compiler.nodes.PiArrayNode.piArrayCast;
+import static org.graalvm.compiler.nodes.PiArrayNode.piArrayCastToSnippetReplaceeStamp;
import static org.graalvm.compiler.nodes.PiNode.piCastToSnippetReplaceeStamp;
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY;
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY;
@@ -226,7 +226,7 @@
return verifyOop(result);
}
- @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true)
+ @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
public static native Object newInstance(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub);
@Snippet
@@ -307,7 +307,7 @@
@ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext,
@ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
Object result = allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters);
- return piArrayCast(verifyOop(result), length);
+ return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
}
private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, Register threadRegister,
@@ -334,20 +334,20 @@
return result;
}
- @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true)
+ @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
public static native Object newArray(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int length, boolean fillContents);
public static final ForeignCallDescriptor DYNAMIC_NEW_ARRAY = new ForeignCallDescriptor("dynamic_new_array", Object.class, Class.class, int.class);
public static final ForeignCallDescriptor DYNAMIC_NEW_INSTANCE = new ForeignCallDescriptor("dynamic_new_instance", Object.class, Class.class);
- @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true)
+ @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
public static native Object dynamicNewArrayStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType, int length);
public static Object dynamicNewInstanceStub(Class<?> elementType) {
return dynamicNewInstanceStubCall(DYNAMIC_NEW_INSTANCE, elementType);
}
- @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true)
+ @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
public static native Object dynamicNewInstanceStubCall(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType);
@Snippet
@@ -396,7 +396,7 @@
int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG);
Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", true, options, counters);
- return piArrayCast(verifyOop(result), length);
+ return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
}
/**
@@ -418,7 +418,7 @@
return newmultiarray(hubPIC, rank, dimensions);
}
- @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true)
+ @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
public static native Object newArrayCall(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int rank, Word dims);
/**
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ReflectionGetCallerClassNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ReflectionGetCallerClassNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -80,7 +80,7 @@
/**
* If inlining is deep enough this method returns a {@link ConstantNode} of the caller class by
- * walking the the stack.
+ * walking the stack.
*
* @param metaAccess
* @return ConstantNode of the caller class, or null
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -22,8 +22,6 @@
*/
package org.graalvm.compiler.hotspot.replacements.arraycopy;
-import jdk.vm.ci.meta.JavaKind;
-
import static org.graalvm.compiler.core.common.LocationIdentity.any;
import org.graalvm.compiler.core.common.LocationIdentity;
@@ -33,11 +31,12 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.compiler.nodes.spi.Virtualizable;
import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode;
+import jdk.vm.ci.meta.JavaKind;
+
@NodeInfo
-public final class ArrayCopyNode extends BasicArrayCopyNode implements Virtualizable, Lowerable {
+public final class ArrayCopyNode extends BasicArrayCopyNode implements Lowerable {
public static final NodeClass<ArrayCopyNode> TYPE = NodeClass.create(ArrayCopyNode.class);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java Thu Apr 06 23:01:27 2017 +0000
@@ -63,6 +63,7 @@
import org.graalvm.compiler.nodes.java.ArrayLengthNode;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.nodes.type.StampTool;
+import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.replacements.SnippetCounter;
import org.graalvm.compiler.replacements.SnippetCounter.Group;
@@ -628,7 +629,7 @@
private void instantiate(Arguments args, BasicArrayCopyNode arraycopy) {
StructuredGraph graph = arraycopy.graph();
SnippetTemplate template = template(args);
- UnmodifiableEconomicMap<Node, Node> replacements = template.instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args);
+ UnmodifiableEconomicMap<Node, Node> replacements = template.instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args, false);
for (Node originalNode : replacements.getKeys()) {
if (originalNode instanceof Invoke) {
Invoke invoke = (Invoke) replacements.get(originalNode);
@@ -643,17 +644,18 @@
if (arraycopy.stateDuring() != null) {
newInvoke.setStateDuring(arraycopy.stateDuring());
} else {
- assert arraycopy.stateAfter() != null;
+ assert arraycopy.stateAfter() != null : arraycopy;
newInvoke.setStateAfter(arraycopy.stateAfter());
}
graph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke);
} else if (originalNode instanceof ArrayCopySlowPathNode) {
ArrayCopySlowPathNode slowPath = (ArrayCopySlowPathNode) replacements.get(originalNode);
- assert arraycopy.stateAfter() != null;
- slowPath.setStateAfter(arraycopy.stateAfter());
+ assert arraycopy.stateAfter() != null : arraycopy;
+ assert slowPath.stateAfter() == arraycopy.stateAfter();
slowPath.setBci(arraycopy.getBci());
}
}
+ GraphUtil.killCFG(arraycopy);
}
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java Thu Apr 06 23:01:27 2017 +0000
@@ -157,6 +157,6 @@
public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_PC = newDescriptor(ExceptionHandlerStub.class, "exceptionHandlerForPc", Word.class, Word.class);
- @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true)
+ @NodeIntrinsic(value = StubForeignCallNode.class)
public static native Word exceptionHandlerForPc(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForPc, Word thread);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java Thu Apr 06 23:01:27 2017 +0000
@@ -32,6 +32,7 @@
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.LocationIdentity;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.StampPair;
import org.graalvm.compiler.debug.Debug;
@@ -57,6 +58,7 @@
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
import jdk.vm.ci.hotspot.HotSpotSignature;
+import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaMethod;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.MetaAccessProvider;
@@ -241,17 +243,13 @@
}
kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result));
- if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) {
- Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Initial stub graph");
- }
+ Debug.dump(Debug.VERBOSE_LEVEL, graph, "Initial stub graph");
kit.inlineInvokes();
new RemoveValueProxyPhase().apply(graph);
- if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) {
- Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Stub graph before compilation");
- }
+ Debug.dump(Debug.VERBOSE_LEVEL, graph, "Stub graph before compilation");
return graph;
}
@@ -269,13 +267,14 @@
}
private StubForeignCallNode createTargetCall(GraphKit kit, ParameterNode[] params, ReadRegisterNode thread) {
+ Stamp stamp = StampFactory.forKind(JavaKind.fromJavaClass(target.getDescriptor().getResultType()));
if (prependThread) {
ValueNode[] targetArguments = new ValueNode[1 + params.length];
targetArguments[0] = thread;
System.arraycopy(params, 0, targetArguments, 1, params.length);
- return kit.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), targetArguments));
+ return kit.append(new StubForeignCallNode(providers.getForeignCalls(), stamp, target.getDescriptor(), targetArguments));
} else {
- return kit.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), params));
+ return kit.append(new StubForeignCallNode(providers.getForeignCalls(), stamp, target.getDescriptor(), params));
}
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java Thu Apr 06 23:01:27 2017 +0000
@@ -25,6 +25,7 @@
import static org.graalvm.compiler.core.GraalCompiler.emitBackEnd;
import static org.graalvm.compiler.core.GraalCompiler.emitFrontEnd;
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
+import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugStubsAndSnippets;
import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER;
import static org.graalvm.util.CollectionsUtil.allMatch;
@@ -35,6 +36,7 @@
import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.debug.Debug;
import org.graalvm.compiler.debug.Debug.Scope;
+import org.graalvm.compiler.debug.DebugConfig;
import org.graalvm.compiler.debug.internal.DebugScope;
import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
@@ -176,7 +178,8 @@
@SuppressWarnings("try")
public synchronized InstalledCode getCode(final Backend backend) {
if (code == null) {
- try (Scope d = Debug.sandbox("CompilingStub", DebugScope.getConfig(), providers.getCodeCache(), debugScopeContext())) {
+ DebugConfig config = DebugStubsAndSnippets.getValue(options) ? DebugScope.getConfig() : Debug.silentConfig();
+ try (Scope d = Debug.sandbox("CompilingStub", config, providers.getCodeCache(), debugScopeContext())) {
CodeCacheProvider codeCache = providers.getCodeCache();
CompilationResult compResult = buildCompilationResult(backend);
@@ -184,7 +187,7 @@
assert destroyedCallerRegisters != null;
// Add a GeneratePIC check here later, we don't want to install
// code if we don't have a corresponding VM global symbol.
- HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(null, null, compResult);
+ HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult);
code = codeCache.installCode(null, compiledCode, null, null, false);
} catch (Throwable e) {
throw Debug.handle(e);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java Thu Apr 06 23:01:27 2017 +0000
@@ -122,6 +122,6 @@
public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_RETURN_ADDRESS = newDescriptor(UnwindExceptionToCallerStub.class, "exceptionHandlerForReturnAddress", Word.class, Word.class,
Word.class);
- @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true)
+ @NodeIntrinsic(value = StubForeignCallNode.class)
public static native Word exceptionHandlerForReturnAddress(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForReturnAddress, Word thread, Word returnAddress);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java Thu Apr 06 23:01:27 2017 +0000
@@ -1051,8 +1051,8 @@
public static BciBlockMapping create(BytecodeStream stream, Bytecode code, OptionValues options) {
BciBlockMapping map = new BciBlockMapping(code);
map.build(stream, options);
- if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) {
- Debug.dump(Debug.INFO_LOG_LEVEL, map, code.getMethod().format("After block building %f %R %H.%n(%P)"));
+ if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) {
+ Debug.dump(Debug.INFO_LEVEL, map, code.getMethod().format("After block building %f %R %H.%n(%P)"));
}
return map;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Thu Apr 06 23:01:27 2017 +0000
@@ -247,7 +247,6 @@
import static org.graalvm.compiler.core.common.type.StampFactory.objectNonNull;
import static org.graalvm.compiler.debug.GraalError.guarantee;
import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere;
-import static org.graalvm.compiler.java.BytecodeParserOptions.DumpDuringGraphBuilding;
import static org.graalvm.compiler.java.BytecodeParserOptions.TraceBytecodeParserLevel;
import static org.graalvm.compiler.java.BytecodeParserOptions.TraceInlineDuringParsing;
import static org.graalvm.compiler.java.BytecodeParserOptions.TraceParserPlugins;
@@ -272,8 +271,8 @@
import org.graalvm.compiler.bytecode.Bytes;
import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider;
+import org.graalvm.compiler.core.common.LocationIdentity;
import org.graalvm.compiler.core.common.PermanentBailoutException;
-import org.graalvm.compiler.core.common.LocationIdentity;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.calc.FloatConvert;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
@@ -770,10 +769,6 @@
for (BciBlock block : blocks) {
processBlock(block);
}
-
- if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL) && DumpDuringGraphBuilding.getValue(options) && this.beforeReturnNode != startInstruction) {
- Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Bytecodes parsed: %s.%s", method.getDeclaringClass().getUnqualifiedName(), method.getName());
- }
}
}
@@ -890,7 +885,7 @@
*/
protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) {
assert !graphBuilderConfig.eagerResolving();
- append(new FixedGuardNode(graph.unique(IsNullNode.create(object)), Unresolved, InvalidateRecompile));
+ append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(object)), Unresolved, InvalidateRecompile));
frameState.push(JavaKind.Object, appendConstant(JavaConstant.NULL_POINTER));
}
@@ -902,7 +897,7 @@
assert !graphBuilderConfig.eagerResolving();
AbstractBeginNode successor = graph.add(new BeginNode());
DeoptimizeNode deopt = graph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved));
- append(new IfNode(graph.unique(IsNullNode.create(object)), successor, deopt, 1));
+ append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(object)), successor, deopt, 1));
lastInstr = successor;
frameState.push(JavaKind.Int, appendConstant(JavaConstant.INT_0));
}
@@ -1060,15 +1055,15 @@
}
protected ValueNode genNegateOp(ValueNode x) {
- return (new NegateNode(x));
+ return NegateNode.create(x);
}
protected ValueNode genLeftShift(ValueNode x, ValueNode y) {
- return new LeftShiftNode(x, y);
+ return LeftShiftNode.create(x, y);
}
protected ValueNode genRightShift(ValueNode x, ValueNode y) {
- return new RightShiftNode(x, y);
+ return RightShiftNode.create(x, y);
}
protected ValueNode genUnsignedRightShift(ValueNode x, ValueNode y) {
@@ -1123,11 +1118,11 @@
}
protected LogicNode genIntegerEquals(ValueNode x, ValueNode y) {
- return IntegerEqualsNode.create(x, y, constantReflection);
+ return IntegerEqualsNode.create(x, y);
}
protected LogicNode genIntegerLessThan(ValueNode x, ValueNode y) {
- return IntegerLessThanNode.create(x, y, constantReflection);
+ return IntegerLessThanNode.create(x, y);
}
protected ValueNode genUnique(ValueNode x) {
@@ -1146,8 +1141,8 @@
genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
ValueNode exception = frameState.pop(JavaKind.Object);
- FixedGuardNode nullCheck = append(new FixedGuardNode(graph.unique(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true));
- PiNode nonNullException = graph.unique(new PiNode(exception, exception.stamp().join(objectNonNull()), nullCheck));
+ FixedGuardNode nullCheck = append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true));
+ ValueNode nonNullException = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp().join(objectNonNull()), nullCheck));
lastInstr.setNext(handleException(nonNullException, bci()));
}
@@ -1172,7 +1167,7 @@
}
protected ValueNode genConditional(ValueNode x) {
- return new ConditionalNode((LogicNode) x);
+ return ConditionalNode.create((LogicNode) x);
}
protected NewInstanceNode createNewInstance(ResolvedJavaType type, boolean fillContents) {
@@ -1190,9 +1185,11 @@
protected ValueNode genLoadField(ValueNode receiver, ResolvedJavaField field) {
StampPair stamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, field.getType(), false);
if (stamp == null) {
- return LoadFieldNode.create(this.graph.getAssumptions(), receiver, field);
+ return LoadFieldNode.create(getConstantFieldProvider(), getConstantReflection(), getMetaAccess(), getOptions(),
+ getAssumptions(), receiver, field, false, false);
} else {
- return LoadFieldNode.createOverrideStamp(stamp, receiver, field);
+ return LoadFieldNode.createOverrideStamp(getConstantFieldProvider(), getConstantReflection(), getMetaAccess(), getOptions(),
+ stamp, receiver, field, false, false);
}
}
@@ -1202,8 +1199,8 @@
}
BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class));
AbstractBeginNode falseSucc = graph.add(new BeginNode());
- PiNode nonNullReceiver = graph.unique(new PiNode(receiver, objectNonNull(), falseSucc));
- append(new IfNode(graph.unique(IsNullNode.create(receiver)), exception, falseSucc, 0.01));
+ ValueNode nonNullReceiver = graph.addOrUnique(PiNode.create(receiver, objectNonNull(), falseSucc));
+ append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(receiver)), exception, falseSucc, 0.01));
lastInstr = falseSucc;
exception.setStateAfter(createFrameState(bci(), exception));
@@ -1215,7 +1212,7 @@
protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) {
AbstractBeginNode trueSucc = graph.add(new BeginNode());
BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index));
- append(new IfNode(graph.unique(IntegerBelowNode.create(index, length, constantReflection)), trueSucc, exception, 0.99));
+ append(new IfNode(genUnique(IntegerBelowNode.create(index, length)), trueSucc, exception, 0.99));
lastInstr = trueSucc;
exception.setStateAfter(createFrameState(bci(), exception));
@@ -1401,11 +1398,6 @@
}
if (invokeKind.hasReceiver()) {
args[0] = emitExplicitExceptions(args[0]);
-
- if (args[0].isNullConstant()) {
- append(new DeoptimizeNode(InvalidateRecompile, NullCheckException));
- return null;
- }
}
InlineInfo inlineInfo = null;
@@ -1419,6 +1411,11 @@
return null;
}
+ if (invokeKind.hasReceiver() && args[0].isNullConstant()) {
+ append(new DeoptimizeNode(InvalidateRecompile, NullCheckException));
+ return null;
+ }
+
if (!invokeKind.isIndirect() || (UseGuardedIntrinsics.getValue(options) && !GeneratePIC.getValue(options))) {
if (tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType)) {
if (TraceParserPlugins.getValue(options)) {
@@ -1611,7 +1608,7 @@
LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver));
LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub));
ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess()));
- LogicNode compare = graph.unique(CompareNode.createCompareNode(Condition.EQ, actual, expected, constantReflection));
+ LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(Condition.EQ, actual, expected, constantReflection));
JavaTypeProfile profile = null;
if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) {
@@ -2125,8 +2122,8 @@
JsrScope scope = currentBlock.getJsrScope();
int retAddress = scope.nextReturnAddress();
ConstantNode returnBciNode = getJsrConstant(retAddress);
- LogicNode guard = IntegerEqualsNode.create(local, returnBciNode, constantReflection);
- guard = graph.unique(guard);
+ LogicNode guard = IntegerEqualsNode.create(local, returnBciNode);
+ guard = graph.addOrUniqueWithInputs(guard);
append(new FixedGuardNode(guard, JavaSubroutineMismatch, InvalidateReprofile));
if (!successor.getJsrScope().equals(scope.pop())) {
throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)");
@@ -2656,7 +2653,7 @@
}
private DebugCloseable openNodeContext() {
- if (graphBuilderConfig.trackNodeSourcePosition() && !parsingIntrinsic()) {
+ if ((graphBuilderConfig.trackNodeSourcePosition() || Debug.isDumpEnabledForMethod()) && !parsingIntrinsic()) {
return graph.withNodeSourcePosition(createBytecodePosition());
}
return null;
@@ -2776,7 +2773,7 @@
genConstantTargetIf(trueBlock, falseBlock, negate, condition);
} else {
if (condition.graph() == null) {
- condition = graph.unique(condition);
+ condition = genUnique(condition);
}
// Need to get probability based on current bci.
@@ -3048,7 +3045,7 @@
int nextBCI = stream.nextBCI();
int nextBC = stream.readUByte(nextBCI);
- if (nextBC == Bytecodes.GETFIELD) {
+ if (nextBCI <= currentBlock.endBci && nextBC == Bytecodes.GETFIELD) {
stream.next();
genGetField(lookupField(stream.readCPI(), Bytecodes.GETFIELD), value);
} else {
@@ -3147,7 +3144,7 @@
default:
throw shouldNotReachHere();
}
- frameState.push(kind, append(v));
+ frameState.push(kind, recursiveAppend(v));
}
private void genIntegerDivOp(JavaKind kind, int opcode) {
@@ -3194,7 +3191,7 @@
default:
throw shouldNotReachHere();
}
- frameState.push(kind, append(v));
+ frameState.push(kind, recursiveAppend(v));
}
private void genLogicOp(JavaKind kind, int opcode) {
@@ -3217,7 +3214,7 @@
default:
throw shouldNotReachHere();
}
- frameState.push(kind, append(v));
+ frameState.push(kind, recursiveAppend(v));
}
private void genCompareOp(JavaKind kind, boolean isUnorderedLess) {
@@ -3236,7 +3233,7 @@
if (from != from.getStackKind()) {
input = append(genNarrow(input, from.getBitCount()));
}
- frameState.push(to, append(genSignExtend(input, to.getBitCount())));
+ frameState.push(to, recursiveAppend(genSignExtend(input, to.getBitCount())));
}
private void genZeroExtend(JavaKind from, JavaKind to) {
@@ -3257,7 +3254,7 @@
int delta = getStream().readIncrement();
ValueNode x = frameState.loadLocal(index, JavaKind.Int);
ValueNode y = appendConstant(JavaConstant.forInt(delta));
- frameState.storeLocal(index, JavaKind.Int, append(genIntegerAdd(x, y)));
+ frameState.storeLocal(index, JavaKind.Int, recursiveAppend(genIntegerAdd(x, y)));
}
private void genIfZero(Condition cond) {
@@ -3373,7 +3370,7 @@
castNode = object;
} else {
FixedGuardNode fixedGuard = append(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile, false));
- castNode = append(new PiNode(object, StampFactory.objectNonNull(TypeReference.createExactTrusted(singleType)), fixedGuard));
+ castNode = append(PiNode.create(object, StampFactory.objectNonNull(TypeReference.createExactTrusted(singleType)), fixedGuard));
}
}
}
@@ -3386,7 +3383,7 @@
castNode = object;
} else {
FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false));
- castNode = append(new PiNode(object, StampFactory.object(checkedType, nonNull), fixedGuard));
+ castNode = append(PiNode.create(object, StampFactory.object(checkedType, nonNull), fixedGuard));
}
}
frameState.push(JavaKind.Object, castNode);
@@ -3431,7 +3428,7 @@
int next = getStream().nextBCI();
int value = getStream().readUByte(next);
- if (value == Bytecodes.IFEQ || value == Bytecodes.IFNE) {
+ if (next <= currentBlock.endBci && (value == Bytecodes.IFEQ || value == Bytecodes.IFNE)) {
getStream().next();
BciBlock firstSucc = currentBlock.getSuccessor(0);
BciBlock secondSucc = currentBlock.getSuccessor(1);
@@ -3678,11 +3675,10 @@
}
private void genGetStatic(JavaField field) {
- if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) {
- handleUnresolvedLoadField(field, null);
+ ResolvedJavaField resolvedField = resolveStaticFieldAccess(field, null);
+ if (resolvedField == null) {
return;
}
- ResolvedJavaField resolvedField = (ResolvedJavaField) field;
if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) {
graph.recordField(resolvedField);
@@ -3712,13 +3708,39 @@
frameState.push(field.getJavaKind(), append(genLoadField(null, resolvedField)));
}
+ private ResolvedJavaField resolveStaticFieldAccess(JavaField field, ValueNode value) {
+ if (field instanceof ResolvedJavaField) {
+ ResolvedJavaField resolvedField = (ResolvedJavaField) field;
+ if (resolvedField.getDeclaringClass().isInitialized()) {
+ return resolvedField;
+ }
+ /*
+ * Static fields have initialization semantics but may be safely accessed under certain
+ * conditions while the class is being initialized. Executing in the clinit or init of
+ * classes which are subtypes of the field holder are sure to be running in a context
+ * where the access is safe.
+ */
+ if (resolvedField.getDeclaringClass().isAssignableFrom(method.getDeclaringClass())) {
+ if (method.isClassInitializer() || method.isConstructor()) {
+ return resolvedField;
+ }
+ }
+ }
+ if (value == null) {
+ handleUnresolvedLoadField(field, null);
+ } else {
+ handleUnresolvedStoreField(field, value, null);
+
+ }
+ return null;
+ }
+
private void genPutStatic(JavaField field) {
ValueNode value = frameState.pop(field.getJavaKind());
- if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) {
- handleUnresolvedStoreField(field, value, null);
+ ResolvedJavaField resolvedField = resolveStaticFieldAccess(field, value);
+ if (resolvedField == null) {
return;
}
- ResolvedJavaField resolvedField = (ResolvedJavaField) field;
if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) {
graph.recordField(resolvedField);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java Thu Apr 06 23:01:27 2017 +0000
@@ -52,9 +52,6 @@
@Option(help = "Maximum depth when inlining during bytecode parsing.", type = OptionType.Debug)
public static final OptionKey<Integer> InlineDuringParsingMaxDepth = new OptionKey<>(10);
- @Option(help = "Dump graphs after non-trivial changes during bytecode parsing.", type = OptionType.Debug)
- public static final OptionKey<Boolean> DumpDuringGraphBuilding = new OptionKey<>(false);
-
@Option(help = "When creating info points hide the methods of the substitutions.", type = OptionType.Debug)
public static final OptionKey<Boolean> HideSubstitutionStates = new OptionKey<>(false);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java Thu Apr 06 23:01:27 2017 +0000
@@ -22,6 +22,11 @@
*/
package org.graalvm.compiler.lir.sparc;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static jdk.vm.ci.sparc.SPARC.CPU;
+import static jdk.vm.ci.sparc.SPARC.g0;
+import static jdk.vm.ci.sparc.SPARCKind.WORD;
+import static jdk.vm.ci.sparc.SPARCKind.XWORD;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CBCOND;
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.FBPCC;
@@ -68,19 +73,14 @@
import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
import static org.graalvm.compiler.lir.sparc.SPARCMove.const2reg;
import static org.graalvm.compiler.lir.sparc.SPARCOP3Op.emitOp3;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
-import static jdk.vm.ci.sparc.SPARC.CPU;
-import static jdk.vm.ci.sparc.SPARC.g0;
-import static jdk.vm.ci.sparc.SPARCKind.WORD;
-import static jdk.vm.ci.sparc.SPARCKind.XWORD;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
+
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.asm.Assembler.LabelHint;
import org.graalvm.compiler.asm.Label;
-import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.asm.sparc.SPARCAssembler;
import org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict;
import org.graalvm.compiler.asm.sparc.SPARCAssembler.CC;
@@ -98,8 +98,8 @@
import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure;
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.util.EconomicMap;
import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.meta.AllocatableValue;
@@ -159,6 +159,7 @@
public CompareBranchOp(AllocatableValue x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, SPARCKind kind, boolean unorderedIsTrue,
double trueDestinationProbability) {
super(TYPE, SIZE);
+ assert x.getPlatformKind() == y.getPlatformKind() : String.format("PlatformKind of x must match PlatformKind of y. %s!=%s", x.getPlatformKind(), y.getPlatformKind());
this.x = x;
this.y = y;
this.trueDestination = trueDestination;
@@ -250,6 +251,7 @@
* @return true if the branch could be emitted
*/
private boolean emitShortCompareBranch(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+ boolean isLong = kind == SPARCKind.XWORD;
ConditionFlag actualConditionFlag = conditionFlag;
Label actualTrueTarget = trueDestination.label();
Label actualFalseTarget = falseDestination.label();
@@ -274,7 +276,7 @@
actualFalseTarget = tmpTarget;
}
}
- emitCBCond(masm, x, y, actualTrueTarget, actualConditionFlag);
+ emitCBCond(masm, x, y, actualTrueTarget, actualConditionFlag, isLong);
if (needJump) {
masm.jmp(actualFalseTarget);
masm.nop();
@@ -282,16 +284,24 @@
return true;
}
- private void emitCBCond(SPARCMacroAssembler masm, Value actualX, Value actualY, Label actualTrueTarget, ConditionFlag cFlag) {
+ private static void emitCBCond(SPARCMacroAssembler masm, Value actualX, Value actualY, Label actualTrueTarget, ConditionFlag cFlag, boolean isLong) {
PlatformKind xKind = actualX.getPlatformKind();
- boolean isLong = kind == SPARCKind.XWORD;
+ Register rs1 = asRegister(actualX, xKind);
if (isJavaConstant(actualY)) {
JavaConstant c = asJavaConstant(actualY);
long constantY = c.isNull() ? 0 : c.asLong();
- assert NumUtil.isInt(constantY);
- CBCOND.emit(masm, cFlag, isLong, asRegister(actualX, xKind), (int) constantY, actualTrueTarget);
+ try (ScratchRegister scratch = masm.getScratchRegister()) {
+ if (SPARCMacroAssembler.isSimm5(constantY)) {
+ CBCOND.emit(masm, cFlag, isLong, rs1, (int) constantY, actualTrueTarget);
+ } else { // !simm5
+ Register rs2 = scratch.getRegister();
+ masm.setx(constantY, rs2, false);
+ CBCOND.emit(masm, cFlag, isLong, rs1, rs2, actualTrueTarget);
+ }
+ }
} else {
- CBCOND.emit(masm, cFlag, isLong, asRegister(actualX, xKind), asRegister(actualY, xKind), actualTrueTarget);
+ Register rs2 = asRegister(actualY, xKind);
+ CBCOND.emit(masm, cFlag, isLong, rs1, rs2, actualTrueTarget);
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java Thu Apr 06 23:01:27 2017 +0000
@@ -217,7 +217,7 @@
/**
* Calculates the entry and exit states for all basic blocks.
*
- * @return Returns true on success and false if the the control flow is too complex.
+ * @return Returns true on success and false if the control flow is too complex.
*/
@SuppressWarnings("try")
private boolean solveDataFlow(LIR lir) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/SwitchStrategy.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/SwitchStrategy.java Thu Apr 06 23:01:27 2017 +0000
@@ -46,7 +46,7 @@
private interface SwitchClosure {
/**
* Generates a conditional or unconditional jump. The jump will be unconditional if
- * condition is null. If defaultTarget is true, then the jump will go the the default.
+ * condition is null. If defaultTarget is true, then the jump will go the default.
*
* @param index Index of the value and the jump target (only used if defaultTarget == false)
* @param condition The condition on which to jump (can be null)
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java Thu Apr 06 23:01:27 2017 +0000
@@ -750,11 +750,11 @@
}
}
}
- Debug.dump(Debug.BASIC_LOG_LEVEL, new LinearScanIntervalDumper(Arrays.copyOf(intervals, intervalsSize)), label);
+ Debug.dump(Debug.BASIC_LEVEL, new LinearScanIntervalDumper(Arrays.copyOf(intervals, intervalsSize)), label);
}
public void printLir(String label, @SuppressWarnings("unused") boolean hirValid) {
- Debug.dump(Debug.INFO_LOG_LEVEL, ir, label);
+ Debug.dump(Debug.INFO_LEVEL, ir, label);
}
boolean verify() {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -110,12 +110,12 @@
interval.setSpillState(SpillState.StoreAtDefinition);
return;
}
- Debug.log(Debug.VERBOSE_LOG_LEVEL, "Spill block candidate (initial): %s", spillBlock);
+ Debug.log(Debug.VERBOSE_LEVEL, "Spill block candidate (initial): %s", spillBlock);
// move out of loops
if (defBlock.getLoopDepth() < spillBlock.getLoopDepth()) {
spillBlock = moveSpillOutOfLoop(defBlock, spillBlock);
}
- Debug.log(Debug.VERBOSE_LOG_LEVEL, "Spill block candidate (after loop optimizaton): %s", spillBlock);
+ Debug.log(Debug.VERBOSE_LEVEL, "Spill block candidate (after loop optimizaton): %s", spillBlock);
/*
* The spill block is the begin of the first split child (aka the value is on the
@@ -134,7 +134,7 @@
spillBlock = dom;
}
if (defBlock.equals(spillBlock)) {
- Debug.log(Debug.VERBOSE_LOG_LEVEL, "Definition is the best choice: %s", defBlock);
+ Debug.log(Debug.VERBOSE_LEVEL, "Definition is the best choice: %s", defBlock);
// definition is the best choice
interval.setSpillState(SpillState.StoreAtDefinition);
return;
@@ -146,7 +146,7 @@
}
if (defBlock.probability() <= spillBlock.probability()) {
- Debug.log(Debug.VERBOSE_LOG_LEVEL, "Definition has lower probability %s (%f) is lower than spill block %s (%f)", defBlock, defBlock.probability(), spillBlock,
+ Debug.log(Debug.VERBOSE_LEVEL, "Definition has lower probability %s (%f) is lower than spill block %s (%f)", defBlock, defBlock.probability(), spillBlock,
spillBlock.probability());
// better spill block has the same probability -> do nothing
interval.setSpillState(SpillState.StoreAtDefinition);
@@ -164,7 +164,7 @@
AllocatableValue fromLocation = interval.getSplitChildAtOpId(spillOpId, OperandMode.DEF, allocator).location();
AllocatableValue toLocation = LinearScan.canonicalSpillOpr(interval);
LIRInstruction move = allocator.getSpillMoveFactory().createMove(toLocation, fromLocation);
- Debug.log(Debug.VERBOSE_LOG_LEVEL, "Insert spill move %s", move);
+ Debug.log(Debug.VERBOSE_LEVEL, "Insert spill move %s", move);
move.setId(LinearScan.DOMINATOR_SPILL_MOVE_ID);
/*
* We can use the insertion buffer directly because we always insert at position 1.
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java Thu Apr 06 23:01:27 2017 +0000
@@ -861,7 +861,7 @@
* errors
*/
allocator.assignSpillSlot(interval);
- Debug.dump(Debug.INFO_LOG_LEVEL, allocator.getLIR(), description);
+ Debug.dump(Debug.INFO_LEVEL, allocator.getLIR(), description);
allocator.printIntervals(description);
throw new OutOfRegistersException("LinearScan: no register found", description);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessAnalysisPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessAnalysisPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -65,7 +65,7 @@
private final class Analyser {
- private static final int LOG_LEVEL = Debug.INFO_LOG_LEVEL;
+ private static final int LOG_LEVEL = Debug.INFO_LEVEL;
/**
* Bit map specifying which operands are live upon entry to this block. These are values
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceBuilderPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceBuilderPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -64,8 +64,8 @@
// @formatter:on
}
- private static final int TRACE_LOG_LEVEL = 1;
- public static final int TRACE_DUMP_LEVEL = 3;
+ private static final int TRACE_LOG_LEVEL = Debug.BASIC_LEVEL;
+ public static final int TRACE_DUMP_LEVEL = Debug.VERBOSE_LEVEL;
@Override
protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceRegisterAllocationPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceRegisterAllocationPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -89,7 +89,7 @@
final TraceRegisterAllocationPolicy plan = DefaultTraceRegisterAllocationPolicy.allocationPolicy(target, lirGenRes, spillMoveFactory, registerAllocationConfig, cachedStackSlots, resultTraces,
neverSpillConstant, livenessInfo, lir.getOptions());
- Debug.dump(Debug.INFO_LOG_LEVEL, lir, "Before TraceRegisterAllocation");
+ Debug.dump(Debug.INFO_LEVEL, lir, "Before TraceRegisterAllocation");
try (Scope s0 = Debug.scope("AllocateTraces", resultTraces, livenessInfo)) {
for (Trace trace : resultTraces.getTraces()) {
tracesCounter.increment();
@@ -101,9 +101,9 @@
} catch (Throwable e) {
throw Debug.handle(e);
}
- if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) {
+ if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) {
unnumberInstructions(lir);
- Debug.dump(Debug.INFO_LOG_LEVEL, lir, "After trace allocation");
+ Debug.dump(Debug.INFO_LEVEL, lir, "After trace allocation");
}
TRACE_GLOBAL_MOVE_RESOLUTION_PHASE.apply(target, lirGenRes, traceContext);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -1073,7 +1073,7 @@
}
}
}
- Debug.dump(Debug.INFO_LOG_LEVEL, this, label);
+ Debug.dump(Debug.INFO_LEVEL, this, label);
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanWalker.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanWalker.java Thu Apr 06 23:01:27 2017 +0000
@@ -954,7 +954,7 @@
* avoid errors
*/
allocator.assignSpillSlot(interval);
- if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) {
+ if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) {
dumpLIRAndIntervals(description);
}
throw new OutOfRegistersException("LinearScan: no register found", description);
@@ -991,7 +991,7 @@
}
protected void dumpLIRAndIntervals(String description) {
- Debug.dump(Debug.INFO_LOG_LEVEL, allocator.getLIR(), description);
+ Debug.dump(Debug.INFO_LEVEL, allocator.getLIR(), description);
allocator.printIntervals(description);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java Thu Apr 06 23:01:27 2017 +0000
@@ -461,7 +461,7 @@
if (block == null) {
return;
}
- boolean emitComment = Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL) || PrintLIRWithAssembly.getValue(getOptions());
+ boolean emitComment = Debug.isDumpEnabled(Debug.BASIC_LEVEL) || PrintLIRWithAssembly.getValue(getOptions());
if (emitComment) {
blockComment(String.format("block B%d %s", block.getId(), block.getLoop()));
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java Thu Apr 06 23:01:27 2017 +0000
@@ -214,7 +214,7 @@
phiConstantsSkipped.increment();
}
phiConstants.set(var.index);
- Debug.log(Debug.VERBOSE_LOG_LEVEL, "Removing phi variable: %s", var);
+ Debug.log(Debug.VERBOSE_LEVEL, "Removing phi variable: %s", var);
}
} else {
assert defined.get(var.index) : "phi but not defined? " + var;
@@ -291,7 +291,7 @@
// no better solution found
materializeAtDefinitionSkipped.increment();
}
- Debug.dump(Debug.INFO_LOG_LEVEL, constTree, "ConstantTree for %s", tree.getVariable());
+ Debug.dump(Debug.DETAILED_LEVEL, constTree, "ConstantTree for %s", tree.getVariable());
}
private void createLoads(DefUseTree tree, ConstantTree constTree, AbstractBlockBase<?> startBlock) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTreeAnalyzer.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTreeAnalyzer.java Thu Apr 06 23:01:27 2017 +0000
@@ -72,19 +72,19 @@
worklist.offerLast(startBlock);
while (!worklist.isEmpty()) {
AbstractBlockBase<?> block = worklist.pollLast();
- try (Indent i = Debug.logAndIndent(Debug.VERBOSE_LOG_LEVEL, "analyze: %s", block)) {
+ try (Indent i = Debug.logAndIndent(Debug.VERBOSE_LEVEL, "analyze: %s", block)) {
assert block != null : "worklist is empty!";
assert isMarked(block) : "Block not part of the dominator tree: " + block;
if (isLeafBlock(block)) {
- Debug.log(Debug.VERBOSE_LOG_LEVEL, "leaf block");
+ Debug.log(Debug.VERBOSE_LEVEL, "leaf block");
leafCost(block);
continue;
}
if (!visited.get(block.getId())) {
// if not yet visited (and not a leaf block) process all children first!
- Debug.log(Debug.VERBOSE_LOG_LEVEL, "not marked");
+ Debug.log(Debug.VERBOSE_LEVEL, "not marked");
worklist.offerLast(block);
AbstractBlockBase<?> dominated = block.getFirstDominated();
while (dominated != null) {
@@ -93,7 +93,7 @@
}
visited.set(block.getId());
} else {
- Debug.log(Debug.VERBOSE_LOG_LEVEL, "marked");
+ Debug.log(Debug.VERBOSE_LEVEL, "marked");
// otherwise, process block
process(block);
}
@@ -162,7 +162,7 @@
private void filteredPush(Deque<AbstractBlockBase<?>> worklist, AbstractBlockBase<?> block) {
if (isMarked(block)) {
- Debug.log(Debug.VERBOSE_LOG_LEVEL, "adding %s to the worklist", block);
+ Debug.log(Debug.VERBOSE_LEVEL, "adding %s to the worklist", block);
worklist.offerLast(block);
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/LIRPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/LIRPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -113,8 +113,8 @@
try (Scope s = Debug.scope(getName(), this)) {
try (DebugCloseable a = timer.start(); DebugCloseable c = memUseTracker.start()) {
run(target, lirGenRes, context);
- if (dumpLIR && Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) {
- Debug.dump(Debug.BASIC_LOG_LEVEL, lirGenRes.getLIR(), "%s", getName());
+ if (dumpLIR && Debug.isDumpEnabled(Debug.BASIC_LEVEL)) {
+ Debug.dump(Debug.BASIC_LEVEL, lirGenRes.getLIR(), "%s", getName());
}
}
} catch (Throwable e) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAVerifier.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAVerifier.java Thu Apr 06 23:01:27 2017 +0000
@@ -87,7 +87,7 @@
doBlock(pred);
}
}
- try (Indent indent = Debug.logAndIndent(Debug.INFO_LOG_LEVEL, "handle block %s", b)) {
+ try (Indent indent = Debug.logAndIndent(Debug.INFO_LEVEL, "handle block %s", b)) {
assert verifyBlock(b);
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java Thu Apr 06 23:01:27 2017 +0000
@@ -131,7 +131,7 @@
@SuppressWarnings("try")
private void allocate() {
- Debug.dump(Debug.INFO_LOG_LEVEL, lir, "After StackSlot numbering");
+ Debug.dump(Debug.INFO_LEVEL, lir, "After StackSlot numbering");
long currentFrameSize = StackSlotAllocatorUtil.allocatedFramesize.isEnabled() ? frameMapBuilder.getFrameMap().currentFrameSize() : 0;
EconomicSet<LIRInstruction> usePos;
@@ -145,14 +145,14 @@
assert verifyIntervals();
}
}
- if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) {
+ if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) {
dumpIntervals("Before stack slot allocation");
}
// step 4: allocate stack slots
try (DebugCloseable t = AllocateSlotsTimer.start()) {
allocateStackSlots();
}
- if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) {
+ if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) {
dumpIntervals("After stack slot allocation");
}
@@ -160,7 +160,7 @@
try (DebugCloseable t = AssignSlotsTimer.start()) {
assignStackSlots(usePos);
}
- Debug.dump(Debug.INFO_LOG_LEVEL, lir, "After StackSlot assignment");
+ Debug.dump(Debug.INFO_LEVEL, lir, "After StackSlot assignment");
if (StackSlotAllocatorUtil.allocatedFramesize.isEnabled()) {
StackSlotAllocatorUtil.allocatedFramesize.add(frameMapBuilder.getFrameMap().currentFrameSize() - currentFrameSize);
}
@@ -256,13 +256,13 @@
*/
location = StackSlot.get(current.kind(), slot.getRawOffset(), slot.getRawAddFrameSize());
StackSlotAllocatorUtil.reusedSlots.increment();
- Debug.log(Debug.BASIC_LOG_LEVEL, "Reuse stack slot %s (reallocated from %s) for virtual stack slot %s", location, slot, virtualSlot);
+ Debug.log(Debug.BASIC_LEVEL, "Reuse stack slot %s (reallocated from %s) for virtual stack slot %s", location, slot, virtualSlot);
} else {
// Allocate new stack slot.
location = frameMapBuilder.getFrameMap().allocateSpillSlot(virtualSlot.getValueKind());
StackSlotAllocatorUtil.virtualFramesize.add(frameMapBuilder.getFrameMap().spillSlotSize(virtualSlot.getValueKind()));
StackSlotAllocatorUtil.allocatedSlots.increment();
- Debug.log(Debug.BASIC_LOG_LEVEL, "New stack slot %s for virtual stack slot %s", location, virtualSlot);
+ Debug.log(Debug.BASIC_LEVEL, "New stack slot %s for virtual stack slot %s", location, virtualSlot);
}
}
Debug.log("Allocate location %s for interval %s", location, current);
@@ -434,7 +434,7 @@
}
private void dumpIntervals(String label) {
- Debug.dump(Debug.INFO_LOG_LEVEL, new StackIntervalDumper(Arrays.copyOf(stackSlotMap, stackSlotMap.length)), label);
+ Debug.dump(Debug.INFO_LEVEL, new StackIntervalDumper(Arrays.copyOf(stackSlotMap, stackSlotMap.length)), label);
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopFullUnrollPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopFullUnrollPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -54,7 +54,7 @@
Debug.log("FullUnroll %s", loop);
LoopTransformations.fullUnroll(loop, context, canonicalizer);
FULLY_UNROLLED_LOOPS.increment();
- Debug.dump(Debug.INFO_LOG_LEVEL, graph, "FullUnroll %s", loop);
+ Debug.dump(Debug.DETAILED_LEVEL, graph, "FullUnroll %s", loop);
peeled = true;
break;
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPeelingPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPeelingPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -45,7 +45,7 @@
if (getPolicies().shouldPeel(loop, data.getCFG(), context.getMetaAccess())) {
Debug.log("Peeling %s", loop);
LoopTransformations.peel(loop);
- Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Peeling %s", loop);
+ Debug.dump(Debug.DETAILED_LEVEL, graph, "Peeling %s", loop);
}
}
data.deleteUnusedNodes();
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopUnswitchingPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopUnswitchingPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -61,7 +61,7 @@
logUnswitch(loop, controlSplits);
}
LoopTransformations.unswitch(loop, controlSplits);
- Debug.dump(Debug.INFO_LOG_LEVEL, graph, "After unswitch %s", controlSplits);
+ Debug.dump(Debug.DETAILED_LEVEL, graph, "After unswitch %s", controlSplits);
UNSWITCHED.increment();
unswitched = true;
break;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopsDataTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopsDataTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -77,8 +77,8 @@
Assert.assertEquals(1, loops.outerFirst().get(0).loop().getDepth());
Assert.assertEquals(1, loops.outerFirst().get(1).loop().getDepth());
Assert.assertEquals(2, loops.outerFirst().get(2).loop().getDepth());
- Assert.assertEquals(2, loops.outerFirst().get(3).loop().getDepth());
- Assert.assertEquals(3, loops.outerFirst().get(4).loop().getDepth());
+ Assert.assertEquals(3, loops.outerFirst().get(3).loop().getDepth());
+ Assert.assertEquals(2, loops.outerFirst().get(4).loop().getDepth());
Assert.assertEquals(2, loops.outerFirst().get(5).loop().getDepth());
Assert.assertEquals(3, loops.outerFirst().get(6).loop().getDepth());
Assert.assertEquals(4, loops.outerFirst().get(7).loop().getDepth());
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedOffsetInductionVariable.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedOffsetInductionVariable.java Thu Apr 06 23:01:27 2017 +0000
@@ -90,7 +90,7 @@
@Override
public ValueNode strideNode() {
if (value instanceof SubNode && base.valueNode() == value.getY()) {
- return graph().unique(new NegateNode(base.strideNode()));
+ return graph().addOrUniqueWithInputs(NegateNode.create(base.strideNode()));
}
return base.strideNode();
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ArrayListBenchmark.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ArrayListBenchmark.java Thu Apr 06 23:01:27 2017 +0000
@@ -24,13 +24,14 @@
import java.util.ArrayList;
+import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
-import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
-
/**
* Benchmarks cost of ArrayList.
*/
@@ -40,7 +41,7 @@
@State(Scope.Benchmark)
public static class ThreadState {
- ArrayList<Integer> list = new ArrayList<>(N);
+ final ArrayList<Integer> list = new ArrayList<>(N);
}
@Benchmark
@@ -61,9 +62,20 @@
state.list.clear();
}
+ @State(Scope.Benchmark)
+ public static class ClearedThreadState {
+ final ArrayList<Integer> list = new ArrayList<>(N);
+
+ // We don't want to measure the cost of list clearing
+ @Setup(Level.Invocation)
+ public void beforeInvocation() {
+ list.clear();
+ }
+ }
+
@Benchmark
@Warmup(iterations = 20)
- public void addNull(ThreadState state) {
+ public void addNull(ClearedThreadState state) {
for (int i = 0; i < N; ++i) {
state.list.add(null);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java Thu Apr 06 23:01:27 2017 +0000
@@ -374,13 +374,17 @@
codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock);
linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock);
- LIR lir = new LIR(cfg, linearScanOrder, codeEmittingOrder, graph.getOptions());
+ LIR lir = new LIR(cfg, linearScanOrder, codeEmittingOrder, getGraphOptions());
FrameMapBuilder frameMapBuilder = request.backend.newFrameMapBuilder(registerConfig);
lirGenRes = request.backend.newLIRGenerationResult(graph.compilationId(), lir, frameMapBuilder, request.graph, stub);
lirGenTool = request.backend.newLIRGenerator(lirGenRes);
nodeLirGen = request.backend.newNodeLIRBuilder(request.graph, lirGenTool);
}
+ protected OptionValues getGraphOptions() {
+ return graph.getOptions();
+ }
+
private static ControlFlowGraph deepCopy(ControlFlowGraph cfg) {
return ControlFlowGraph.compute(cfg.graph, true, true, true, true);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/trace/TraceLSRAIntervalBuildingBench.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/trace/TraceLSRAIntervalBuildingBench.java Thu Apr 06 23:01:27 2017 +0000
@@ -28,6 +28,7 @@
import org.graalvm.compiler.lir.alloc.trace.GlobalLivenessAnalysisPhase;
import org.graalvm.compiler.lir.alloc.trace.GlobalLivenessInfo;
import org.graalvm.compiler.lir.alloc.trace.TraceBuilderPhase;
+import org.graalvm.compiler.lir.alloc.trace.TraceRegisterAllocationPhase;
import org.graalvm.compiler.lir.alloc.trace.lsra.TraceLinearScanLifetimeAnalysisPhase;
import org.graalvm.compiler.lir.alloc.trace.lsra.TraceLinearScanLifetimeAnalysisPhase.Analyser;
import org.graalvm.compiler.lir.alloc.trace.lsra.TraceLinearScanPhase;
@@ -40,6 +41,7 @@
import org.graalvm.compiler.lir.phases.LIRSuites;
import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
import org.graalvm.compiler.microbenchmarks.lir.GraalCompilerState;
+import org.graalvm.compiler.options.OptionValues;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Param;
@@ -90,6 +92,11 @@
return new LIRSuites(ls.getPreAllocationOptimizationStage(), allocationStage, ls.getPostAllocationOptimizationStage());
}
+ @Override
+ protected OptionValues getGraphOptions() {
+ return new OptionValues(super.getGraphOptions(), TraceRegisterAllocationPhase.Options.TraceRAuseInterTraceHints, false);
+ }
+
@Setup(Level.Trial)
public void setup() {
initializeMethod();
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -86,8 +86,8 @@
/*
* Don't allow guards with action None and reason RuntimeConstraint to float. In cases
* where 2 guards are testing equivalent conditions they might be lowered at the same
- * location. If the guard with the None action is lowered before the the other guard
- * then the code will be stuck repeatedly deoptimizing without invalidating the code.
+ * location. If the guard with the None action is lowered before the other guard then
+ * the code will be stuck repeatedly deoptimizing without invalidating the code.
* Conditional elimination will eliminate the guard if it's truly redundant in this
* case.
*/
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java Thu Apr 06 23:01:27 2017 +0000
@@ -105,7 +105,7 @@
*/
@OptionalInput NodeInputList<ValueNode> values;
- @OptionalInput(Association) NodeInputList<MonitorIdNode> monitorIds;
+ @Input(Association) NodeInputList<MonitorIdNode> monitorIds;
@OptionalInput(State) NodeInputList<EscapeObjectState> virtualObjectMappings;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java Thu Apr 06 23:01:27 2017 +0000
@@ -37,8 +37,8 @@
import java.util.SortedMap;
import java.util.TreeMap;
+import org.graalvm.compiler.core.common.Fields;
import org.graalvm.compiler.core.common.PermanentBailoutException;
-import org.graalvm.compiler.core.common.Fields;
import org.graalvm.compiler.core.common.util.TypeReader;
import org.graalvm.compiler.core.common.util.UnsafeArrayTypeReader;
import org.graalvm.compiler.debug.Debug;
@@ -61,9 +61,9 @@
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin.LoopExplosionKind;
-import org.graalvm.util.Equivalence;
import org.graalvm.util.EconomicMap;
import org.graalvm.util.EconomicSet;
+import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.meta.DeoptimizationAction;
@@ -85,8 +85,6 @@
protected class MethodScope {
/** The loop that contains the call. Only non-null during method inlining. */
public final LoopScope callerLoopScope;
- /** The target graph where decoded nodes are added to. */
- public final StructuredGraph graph;
/**
* Mark for nodes that were present before the decoding of this method started. Note that
* nodes that were decoded after the mark can still be part of an outer method, since
@@ -95,20 +93,19 @@
public final Graph.Mark methodStartMark;
/** The encode graph that is decoded. */
public final EncodedGraph encodedGraph;
+ /** The highest node order id that a fixed node has in the EncodedGraph. */
+ public final int maxFixedNodeOrderId;
/** Access to the encoded graph. */
public final TypeReader reader;
/** The kind of loop explosion to be performed during decoding. */
public final LoopExplosionKind loopExplosion;
- /** A list of tasks to run before the method scope is closed. */
- public final List<Runnable> cleanupTasks;
/** All return nodes encountered during decoding. */
- public final List<ReturnNode> returnNodes;
- /** The exception unwind node encountered during decoding, or null. */
- public final List<UnwindNode> unwindNodes;
+ public final List<ControlSinkNode> returnAndUnwindNodes;
/** All merges created during loop explosion. */
public final EconomicSet<Node> loopExplosionMerges;
+
/**
* The start of explosion, and the merge point for when irreducible loops are detected. Only
* used when {@link MethodScope#loopExplosion} is {@link LoopExplosionKind#MERGE_EXPLODE}.
@@ -117,16 +114,14 @@
protected MethodScope(LoopScope callerLoopScope, StructuredGraph graph, EncodedGraph encodedGraph, LoopExplosionKind loopExplosion) {
this.callerLoopScope = callerLoopScope;
- this.graph = graph;
this.methodStartMark = graph.getMark();
this.encodedGraph = encodedGraph;
this.loopExplosion = loopExplosion;
- this.cleanupTasks = new ArrayList<>(2);
- this.returnNodes = new ArrayList<>(1);
- this.unwindNodes = new ArrayList<>(0);
+ this.returnAndUnwindNodes = new ArrayList<>(2);
if (encodedGraph != null) {
reader = UnsafeArrayTypeReader.create(encodedGraph.getEncoding(), encodedGraph.getStartOffset(), architecture.supportsUnalignedMemoryAccess());
+ maxFixedNodeOrderId = reader.getUVInt();
if (encodedGraph.nodeStartOffsets == null) {
int nodeCount = reader.getUVInt();
int[] nodeStartOffsets = new int[nodeCount];
@@ -137,6 +132,7 @@
}
} else {
reader = null;
+ maxFixedNodeOrderId = 0;
}
if (loopExplosion != LoopExplosionKind.NONE) {
@@ -145,6 +141,10 @@
loopExplosionMerges = null;
}
}
+
+ public boolean isInlinedMethod() {
+ return false;
+ }
}
/** Decoding state maintained for each loop in the encoded graph. */
@@ -175,23 +175,24 @@
public final Node[] createdNodes;
/**
* Nodes that have been created in outer loop scopes and existed before starting to process
- * this loop, indexed by the orderId.
+ * this loop, indexed by the orderId. Only used when {@link MethodScope#loopExplosion} is
+ * not {@link LoopExplosionKind#NONE}.
*/
public final Node[] initialCreatedNodes;
protected LoopScope(MethodScope methodScope) {
this.methodScope = methodScope;
this.outer = null;
- this.nextIterations = methodScope.loopExplosion == LoopExplosionKind.FULL_EXPLODE_UNTIL_RETURN ? new ArrayDeque<>() : null;
+ this.nextIterations = methodScope.loopExplosion == LoopExplosionKind.FULL_EXPLODE_UNTIL_RETURN ? new ArrayDeque<>(2) : null;
this.loopDepth = 0;
this.loopIteration = 0;
this.iterationStates = null;
this.loopBeginOrderId = -1;
int nodeCount = methodScope.encodedGraph.nodeStartOffsets.length;
- this.nodesToProcess = new BitSet(nodeCount);
- this.initialCreatedNodes = new Node[nodeCount];
+ this.nodesToProcess = new BitSet(methodScope.maxFixedNodeOrderId);
this.createdNodes = new Node[nodeCount];
+ this.initialCreatedNodes = null;
}
protected LoopScope(MethodScope methodScope, LoopScope outer, int loopDepth, int loopIteration, int loopBeginOrderId, Node[] initialCreatedNodes, Node[] createdNodes,
@@ -203,9 +204,9 @@
this.nextIterations = nextIterations;
this.iterationStates = iterationStates;
this.loopBeginOrderId = loopBeginOrderId;
- this.nodesToProcess = new BitSet(initialCreatedNodes.length);
+ this.nodesToProcess = new BitSet(methodScope.maxFixedNodeOrderId);
this.initialCreatedNodes = initialCreatedNodes;
- this.createdNodes = Arrays.copyOf(createdNodes, createdNodes.length);
+ this.createdNodes = createdNodes;
}
@Override
@@ -338,18 +339,23 @@
}
protected final Architecture architecture;
+ /** The target graph where decoded nodes are added to. */
+ protected final StructuredGraph graph;
+ private final EconomicMap<NodeClass<?>, ArrayDeque<Node>> reusableFloatingNodes;
- public GraphDecoder(Architecture architecture) {
+ public GraphDecoder(Architecture architecture, StructuredGraph graph) {
this.architecture = architecture;
+ this.graph = graph;
+ reusableFloatingNodes = EconomicMap.create(Equivalence.IDENTITY);
}
@SuppressWarnings("try")
- public final void decode(StructuredGraph graph, EncodedGraph encodedGraph) {
+ public final void decode(EncodedGraph encodedGraph) {
try (Debug.Scope scope = Debug.scope("GraphDecoder", graph)) {
MethodScope methodScope = new MethodScope(null, graph, encodedGraph, LoopExplosionKind.NONE);
decode(createInitialLoopScope(methodScope, null));
cleanupGraph(methodScope);
- assert methodScope.graph.verify();
+ assert graph.verify();
} catch (Throwable ex) {
Debug.handle(ex);
}
@@ -370,14 +376,10 @@
startNode.setNext(firstNode);
loopScope.nodesToProcess.set(GraphEncoder.FIRST_NODE_ORDER_ID);
} else {
- firstNode = methodScope.graph.start();
+ firstNode = graph.start();
registerNode(loopScope, GraphEncoder.START_NODE_ORDER_ID, firstNode, false, false);
loopScope.nodesToProcess.set(GraphEncoder.START_NODE_ORDER_ID);
}
-
- if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) {
- methodScope.cleanupTasks.add(new LoopDetector(methodScope, startNode));
- }
return loopScope;
}
@@ -411,18 +413,26 @@
}
/*
- * Finished with an inlined method. Perform all registered end-of-method cleanup tasks
- * and continue with loop that contained the call.
+ * Finished with an inlined method. Perform end-of-method cleanup tasks.
*/
- for (Runnable task : methodScope.cleanupTasks) {
- task.run();
+ if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) {
+ LoopDetector loopDetector = new LoopDetector(graph, methodScope);
+ loopDetector.run();
}
+ if (methodScope.isInlinedMethod()) {
+ finishInlining(methodScope);
+ }
+
+ /* continue with the caller */
loopScope = methodScope.callerLoopScope;
}
}
+ protected void finishInlining(@SuppressWarnings("unused") MethodScope inlineScope) {
+ }
+
private static void propagateCreatedNodes(LoopScope loopScope) {
- if (loopScope.outer == null) {
+ if (loopScope.outer == null || loopScope.createdNodes != loopScope.outer.createdNodes) {
return;
}
@@ -474,7 +484,7 @@
LoopScope outerScope = loopScope.outer;
int nextIterationNumber = outerScope.nextIterations.isEmpty() ? outerScope.loopIteration + 1 : outerScope.nextIterations.getLast().loopIteration + 1;
successorAddScope = new LoopScope(methodScope, outerScope.outer, outerScope.loopDepth, nextIterationNumber, outerScope.loopBeginOrderId, outerScope.initialCreatedNodes,
- loopScope.initialCreatedNodes, outerScope.nextIterations, outerScope.iterationStates);
+ Arrays.copyOf(loopScope.initialCreatedNodes, loopScope.initialCreatedNodes.length), outerScope.nextIterations, outerScope.iterationStates);
checkLoopExplosionIteration(methodScope, successorAddScope);
/*
@@ -496,8 +506,8 @@
methodScope.reader.setByteIndex(methodScope.encodedGraph.nodeStartOffsets[nodeOrderId]);
int typeId = methodScope.reader.getUVInt();
assert node.getNodeClass() == methodScope.encodedGraph.getNodeClasses()[typeId];
+ makeFixedNodeInputs(methodScope, loopScope, node);
readProperties(methodScope, node);
- makeInputNodes(methodScope, loopScope, node, true);
makeSuccessorStubs(methodScope, successorAddScope, node, updatePredecessors);
LoopScope resultScope = loopScope;
@@ -533,13 +543,16 @@
if (merge instanceof LoopBeginNode) {
assert phiNodeScope == phiInputScope && phiNodeScope == loopScope;
resultScope = new LoopScope(methodScope, loopScope, loopScope.loopDepth + 1, 0, mergeOrderId,
- Arrays.copyOf(loopScope.createdNodes, loopScope.createdNodes.length), loopScope.createdNodes, //
- methodScope.loopExplosion != LoopExplosionKind.NONE ? new ArrayDeque<>() : null, //
+ methodScope.loopExplosion != LoopExplosionKind.NONE ? Arrays.copyOf(loopScope.createdNodes, loopScope.createdNodes.length) : null,
+ methodScope.loopExplosion != LoopExplosionKind.NONE ? Arrays.copyOf(loopScope.createdNodes, loopScope.createdNodes.length) : loopScope.createdNodes, //
+ methodScope.loopExplosion != LoopExplosionKind.NONE ? new ArrayDeque<>(2) : null, //
methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE ? EconomicMap.create(Equivalence.DEFAULT) : null);
phiInputScope = resultScope;
phiNodeScope = resultScope;
- registerNode(loopScope, mergeOrderId, null, true, true);
+ if (methodScope.loopExplosion != LoopExplosionKind.NONE) {
+ registerNode(loopScope, mergeOrderId, null, true, true);
+ }
loopScope.nodesToProcess.clear(mergeOrderId);
resultScope.nodesToProcess.set(mergeOrderId);
}
@@ -551,11 +564,8 @@
InvokeData invokeData = readInvokeData(methodScope, nodeOrderId, (Invoke) node);
resultScope = handleInvoke(methodScope, loopScope, invokeData);
- } else if (node instanceof ReturnNode) {
- methodScope.returnNodes.add((ReturnNode) node);
- } else if (node instanceof UnwindNode) {
- methodScope.unwindNodes.add((UnwindNode) node);
-
+ } else if (node instanceof ReturnNode || node instanceof UnwindNode) {
+ methodScope.returnAndUnwindNodes.add((ControlSinkNode) node);
} else {
handleFixedNode(methodScope, loopScope, nodeOrderId, node);
}
@@ -642,7 +652,7 @@
}
}
- MergeNode merge = methodScope.graph.add(new MergeNode());
+ MergeNode merge = graph.add(new MergeNode());
methodScope.loopExplosionMerges.add(merge);
if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) {
@@ -655,11 +665,11 @@
List<ValueNode> newFrameStateValues = new ArrayList<>();
for (ValueNode frameStateValue : frameState.values) {
- if (frameStateValue == null || frameStateValue.isConstant() || !methodScope.graph.isNew(methodScope.methodStartMark, frameStateValue)) {
+ if (frameStateValue == null || frameStateValue.isConstant() || !graph.isNew(methodScope.methodStartMark, frameStateValue)) {
newFrameStateValues.add(frameStateValue);
} else {
- ProxyPlaceholder newFrameStateValue = methodScope.graph.unique(new ProxyPlaceholder(frameStateValue, merge));
+ ProxyPlaceholder newFrameStateValue = graph.unique(new ProxyPlaceholder(frameStateValue, merge));
newFrameStateValues.add(newFrameStateValue);
/*
@@ -670,14 +680,19 @@
if (loopScope.createdNodes[i] == frameStateValue) {
loopScope.createdNodes[i] = newFrameStateValue;
}
- if (loopScope.initialCreatedNodes[i] == frameStateValue) {
- loopScope.initialCreatedNodes[i] = newFrameStateValue;
+ }
+
+ if (loopScope.initialCreatedNodes != null) {
+ for (int i = 0; i < loopScope.initialCreatedNodes.length; i++) {
+ if (loopScope.initialCreatedNodes[i] == frameStateValue) {
+ loopScope.initialCreatedNodes[i] = newFrameStateValue;
+ }
}
}
}
}
- FrameState newFrameState = methodScope.graph.add(new FrameState(frameState.outerFrameState(), frameState.getCode(), frameState.bci, newFrameStateValues, frameState.localsSize(),
+ FrameState newFrameState = graph.add(new FrameState(frameState.outerFrameState(), frameState.getCode(), frameState.bci, newFrameStateValues, frameState.localsSize(),
frameState.stackSize(), frameState.rethrowException(), frameState.duringCall(), frameState.monitorIds(), frameState.virtualObjectMappings()));
frameState.replaceAtUsagesAndDelete(newFrameState);
@@ -708,7 +723,7 @@
}
protected FixedNode handleLoopExplosionEnd(MethodScope methodScope, LoopScope loopScope, LoopEndNode loopEnd) {
- EndNode replacementNode = methodScope.graph.add(new EndNode());
+ EndNode replacementNode = graph.add(new EndNode());
loopEnd.replaceAtPredecessor(replacementNode);
loopEnd.safeDelete();
@@ -716,7 +731,7 @@
if (methodScope.loopExplosion != LoopExplosionKind.FULL_UNROLL || loopScope.nextIterations.isEmpty()) {
int nextIterationNumber = loopScope.nextIterations.isEmpty() ? loopScope.loopIteration + 1 : loopScope.nextIterations.getLast().loopIteration + 1;
LoopScope nextIterationScope = new LoopScope(methodScope, loopScope.outer, loopScope.loopDepth, nextIterationNumber, loopScope.loopBeginOrderId, loopScope.initialCreatedNodes,
- loopScope.initialCreatedNodes, loopScope.nextIterations, loopScope.iterationStates);
+ Arrays.copyOf(loopScope.initialCreatedNodes, loopScope.initialCreatedNodes.length), loopScope.nextIterations, loopScope.iterationStates);
checkLoopExplosionIteration(methodScope, nextIterationScope);
loopScope.nextIterations.addLast(nextIterationScope);
registerNode(nextIterationScope, loopScope.loopBeginOrderId, null, true, true);
@@ -749,7 +764,9 @@
* The ProxyNode transports a value from the loop to the outer scope. We therefore
* register it in the outer scope.
*/
- registerNode(loopScope.outer, proxyOrderId, proxy, false, false);
+ if (loopScope.outer.createdNodes != loopScope.createdNodes) {
+ registerNode(loopScope.outer, proxyOrderId, proxy, false, false);
+ }
}
}
@@ -757,7 +774,7 @@
assert loopExit.stateAfter() == null;
int stateAfterOrderId = readOrderId(methodScope);
- BeginNode begin = methodScope.graph.add(new BeginNode());
+ BeginNode begin = graph.add(new BeginNode());
FixedNode loopExitSuccessor = loopExit.next();
loopExit.replaceAtPredecessor(begin);
@@ -768,14 +785,14 @@
* This exit might end up as a loop exit of a loop detected after partial evaluation. We
* need to be able to create a FrameState and the necessary proxy nodes in this case.
*/
- loopExitPlaceholder = methodScope.graph.add(new MergeNode());
+ loopExitPlaceholder = graph.add(new MergeNode());
methodScope.loopExplosionMerges.add(loopExitPlaceholder);
- EndNode end = methodScope.graph.add(new EndNode());
+ EndNode end = graph.add(new EndNode());
begin.setNext(end);
loopExitPlaceholder.addForwardEnd(end);
- begin = methodScope.graph.add(new BeginNode());
+ begin = graph.add(new BeginNode());
loopExitPlaceholder.setNext(begin);
}
@@ -793,10 +810,10 @@
} else if (existingExit instanceof BeginNode) {
/* Second loop iteration that exits. Create the merge. */
- merge = methodScope.graph.add(new MergeNode());
+ merge = graph.add(new MergeNode());
registerNode(outerScope, loopExitOrderId, merge, true, false);
/* Add the first iteration. */
- EndNode firstEnd = methodScope.graph.add(new EndNode());
+ EndNode firstEnd = graph.add(new EndNode());
((BeginNode) existingExit).setNext(firstEnd);
merge.addForwardEnd(firstEnd);
merge.setNext(loopExitSuccessor);
@@ -807,7 +824,7 @@
}
if (merge != null) {
- EndNode end = methodScope.graph.add(new EndNode());
+ EndNode end = graph.add(new EndNode());
begin.setNext(end);
merge.addForwardEnd(end);
}
@@ -826,7 +843,7 @@
if (loopExitPlaceholder != null) {
if (!phiInput.isConstant()) {
- phiInput = methodScope.graph.unique(new ProxyPlaceholder(phiInput, loopExitPlaceholder));
+ phiInput = graph.unique(new ProxyPlaceholder(phiInput, loopExitPlaceholder));
}
registerNode(loopScope, proxyOrderId, phiInput, true, false);
}
@@ -843,7 +860,14 @@
} else if (!merge.isPhiAtMerge(existing)) {
/* Now we have two different values, so we need to create a phi node. */
- PhiNode phi = methodScope.graph.addWithoutUnique(new ValuePhiNode(proxy.stamp(), merge));
+ PhiNode phi;
+ if (proxy instanceof ValueProxyNode) {
+ phi = graph.addWithoutUnique(new ValuePhiNode(proxy.stamp(), merge));
+ } else if (proxy instanceof GuardProxyNode) {
+ phi = graph.addWithoutUnique(new GuardPhiNode(merge));
+ } else {
+ throw GraalError.shouldNotReachHere();
+ }
/* Add the inputs from all previous exits. */
for (int j = 0; j < merge.phiPredecessorCount() - 1; j++) {
phi.addInput(existing);
@@ -954,12 +978,6 @@
return false;
}
- protected Node instantiateNode(MethodScope methodScope, int nodeOrderId) {
- methodScope.reader.setByteIndex(methodScope.encodedGraph.nodeStartOffsets[nodeOrderId]);
- NodeClass<?> nodeClass = methodScope.encodedGraph.getNodeClasses()[methodScope.reader.getUVInt()];
- return nodeClass.allocateInstance();
- }
-
protected void readProperties(MethodScope methodScope, Node node) {
node.setNodeSourcePosition((NodeSourcePosition) readObject(methodScope));
Fields fields = node.getNodeClass().getData();
@@ -980,7 +998,7 @@
* are created on demand (recursively since they can themselves reference not yet created
* nodes).
*/
- protected void makeInputNodes(MethodScope methodScope, LoopScope loopScope, Node node, boolean updateUsages) {
+ protected void makeFixedNodeInputs(MethodScope methodScope, LoopScope loopScope, Node node) {
Edges edges = node.getNodeClass().getInputEdges();
for (int index = 0; index < edges.getDirectCount(); index++) {
if (skipDirectEdge(node, edges, index)) {
@@ -989,25 +1007,60 @@
int orderId = readOrderId(methodScope);
Node value = ensureNodeCreated(methodScope, loopScope, orderId);
edges.initializeNode(node, index, value);
- if (updateUsages && value != null && !value.isDeleted()) {
+ if (value != null && !value.isDeleted()) {
edges.update(node, null, value);
}
}
- for (int index = edges.getDirectCount(); index < edges.getCount(); index++) {
- if (skipIndirectEdge(node, edges, index, true)) {
- continue;
+
+ if (node instanceof AbstractMergeNode) {
+ /* The ends of merge nodes are filled manually when the ends are processed. */
+ assert edges.getCount() - edges.getDirectCount() == 1 : "MergeNode has one variable size input (the ends)";
+ assert Edges.getNodeList(node, edges.getOffsets(), edges.getDirectCount()) != null : "Input list must have been already created";
+ } else {
+ for (int index = edges.getDirectCount(); index < edges.getCount(); index++) {
+ int size = methodScope.reader.getSVInt();
+ if (size != -1) {
+ NodeList<Node> nodeList = new NodeInputList<>(node, size);
+ edges.initializeList(node, index, nodeList);
+ for (int idx = 0; idx < size; idx++) {
+ int orderId = readOrderId(methodScope);
+ Node value = ensureNodeCreated(methodScope, loopScope, orderId);
+ nodeList.initialize(idx, value);
+ if (value != null && !value.isDeleted()) {
+ edges.update(node, null, value);
+ }
+ }
+ }
}
- int size = methodScope.reader.getSVInt();
- if (size != -1) {
- NodeList<Node> nodeList = new NodeInputList<>(node, size);
- edges.initializeList(node, index, nodeList);
- for (int idx = 0; idx < size; idx++) {
- int orderId = readOrderId(methodScope);
- Node value = ensureNodeCreated(methodScope, loopScope, orderId);
- nodeList.initialize(idx, value);
- if (updateUsages && value != null && !value.isDeleted()) {
- edges.update(node, null, value);
+ }
+ }
+
+ protected void makeFloatingNodeInputs(MethodScope methodScope, LoopScope loopScope, Node node) {
+ Edges edges = node.getNodeClass().getInputEdges();
+ if (node instanceof PhiNode) {
+ /*
+ * The inputs of phi functions are filled manually when the end nodes are processed.
+ * However, the values must not be null, so initialize them with an empty list.
+ */
+ assert edges.getDirectCount() == 1 : "PhiNode has one direct input (the MergeNode)";
+ assert edges.getCount() - edges.getDirectCount() == 1 : "PhiNode has one variable size input (the values)";
+ edges.initializeList(node, edges.getDirectCount(), new NodeInputList<>(node));
+ } else {
+ for (int index = 0; index < edges.getDirectCount(); index++) {
+ int orderId = readOrderId(methodScope);
+ Node value = ensureNodeCreated(methodScope, loopScope, orderId);
+ edges.initializeNode(node, index, value);
+ }
+ for (int index = edges.getDirectCount(); index < edges.getCount(); index++) {
+ int size = methodScope.reader.getSVInt();
+ if (size != -1) {
+ NodeList<Node> nodeList = new NodeInputList<>(node, size);
+ edges.initializeList(node, index, nodeList);
+ for (int idx = 0; idx < size; idx++) {
+ int orderId = readOrderId(methodScope);
+ Node value = ensureNodeCreated(methodScope, loopScope, orderId);
+ nodeList.initialize(idx, value);
}
}
}
@@ -1024,31 +1077,34 @@
}
node = decodeFloatingNode(methodScope, loopScope, nodeOrderId);
-
if (node instanceof ProxyNode || node instanceof PhiNode) {
/*
* We need these nodes as they were in the original graph, without any canonicalization
* or value numbering.
*/
- node = methodScope.graph.addWithoutUnique(node);
+ node = graph.addWithoutUnique(node);
} else {
/* Allow subclasses to canonicalize and intercept nodes. */
- node = handleFloatingNodeBeforeAdd(methodScope, loopScope, node);
- if (!node.isAlive()) {
- node = addFloatingNode(methodScope, node);
+ Node newNode = handleFloatingNodeBeforeAdd(methodScope, loopScope, node);
+ if (newNode != node) {
+ releaseFloatingNode(node);
}
- node = handleFloatingNodeAfterAdd(methodScope, loopScope, node);
+
+ if (!newNode.isAlive()) {
+ newNode = addFloatingNode(methodScope, newNode);
+ }
+ node = handleFloatingNodeAfterAdd(methodScope, loopScope, newNode);
}
registerNode(loopScope, nodeOrderId, node, false, false);
return node;
}
- protected Node addFloatingNode(MethodScope methodScope, Node node) {
+ protected Node addFloatingNode(@SuppressWarnings("unused") MethodScope methodScope, Node node) {
/*
* We want to exactly reproduce the encoded graph. Even though nodes should be unique in the
* encoded graph, this is not always guaranteed.
*/
- return methodScope.graph.addWithoutUnique(node);
+ return graph.addWithoutUnique(node);
}
/**
@@ -1056,7 +1112,10 @@
*/
protected Node decodeFloatingNode(MethodScope methodScope, LoopScope loopScope, int nodeOrderId) {
long readerByteIndex = methodScope.reader.getByteIndex();
- Node node = instantiateNode(methodScope, nodeOrderId);
+
+ methodScope.reader.setByteIndex(methodScope.encodedGraph.nodeStartOffsets[nodeOrderId]);
+ NodeClass<?> nodeClass = methodScope.encodedGraph.getNodeClasses()[methodScope.reader.getUVInt()];
+ Node node = allocateFloatingNode(nodeClass);
if (node instanceof FixedNode) {
/*
* This is a severe error that will lead to a corrupted graph, so it is better not to
@@ -1065,16 +1124,38 @@
throw shouldNotReachHere("Not a floating node: " + node.getClass().getName());
}
+ /* Read the inputs of the node, possibly creating them recursively. */
+ makeFloatingNodeInputs(methodScope, loopScope, node);
+
/* Read the properties of the node. */
readProperties(methodScope, node);
/* There must not be any successors to read, since it is a non-fixed node. */
assert node.getNodeClass().getEdges(Edges.Type.Successors).getCount() == 0;
- /* Read the inputs of the node, possibly creating them recursively. */
- makeInputNodes(methodScope, loopScope, node, false);
+
methodScope.reader.setByteIndex(readerByteIndex);
return node;
}
+ private Node allocateFloatingNode(NodeClass<?> nodeClass) {
+ ArrayDeque<? extends Node> cachedNodes = reusableFloatingNodes.get(nodeClass);
+ if (cachedNodes != null) {
+ Node node = cachedNodes.poll();
+ if (node != null) {
+ return node;
+ }
+ }
+ return nodeClass.allocateInstance();
+ }
+
+ private void releaseFloatingNode(Node node) {
+ ArrayDeque<Node> cachedNodes = reusableFloatingNodes.get(node.getNodeClass());
+ if (cachedNodes == null) {
+ cachedNodes = new ArrayDeque<>(2);
+ reusableFloatingNodes.put(node.getNodeClass(), cachedNodes);
+ }
+ cachedNodes.push(node);
+ }
+
/**
* Hook for subclasses to process a non-fixed node before it is added to the graph.
*
@@ -1121,9 +1202,6 @@
}
}
for (int index = edges.getDirectCount(); index < edges.getCount(); index++) {
- if (skipIndirectEdge(node, edges, index, true)) {
- continue;
- }
int size = methodScope.reader.getSVInt();
if (size != -1) {
NodeList<Node> nodeList = new NodeSuccessorList<>(node, size);
@@ -1150,7 +1228,9 @@
}
long readerByteIndex = methodScope.reader.getByteIndex();
- node = (FixedNode) methodScope.graph.add(instantiateNode(methodScope, nodeOrderId));
+ methodScope.reader.setByteIndex(methodScope.encodedGraph.nodeStartOffsets[nodeOrderId]);
+ NodeClass<?> nodeClass = methodScope.encodedGraph.getNodeClasses()[methodScope.reader.getUVInt()];
+ node = (FixedNode) graph.add(nodeClass.allocateInstance());
/* Properties and edges are not filled yet, the node remains uninitialized. */
methodScope.reader.setByteIndex(readerByteIndex);
@@ -1174,12 +1254,6 @@
return true;
}
}
- } else if (node instanceof PhiNode) {
- /* The inputs of phi functions are filled manually when the end nodes are processed. */
- assert edges.type() == Edges.Type.Inputs;
- assert index == edges.getDirectCount() - 1 : "PhiNode has one direct input (the MergeNode)";
- return true;
-
} else if (node instanceof LoopExitNode && edges.type() == Edges.Type.Inputs && edges.getType(index) == FrameState.class) {
/* The stateAfter of the loop exit is filled manually. */
return true;
@@ -1188,29 +1262,6 @@
return false;
}
- protected static boolean skipIndirectEdge(Node node, Edges edges, int index, boolean decode) {
- assert !(node instanceof Invoke);
- assert !(node instanceof LoopExitNode && edges.type() == Edges.Type.Inputs && edges.getType(index) == FrameState.class);
- if (node instanceof AbstractMergeNode && edges.type() == Edges.Type.Inputs) {
- /* The ends of merge nodes are filled manually when the ends are processed. */
- assert index == edges.getCount() - 1 : "MergeNode has one variable size input (the ends)";
- assert Edges.getNodeList(node, edges.getOffsets(), index) != null : "Input list must have been already created";
- return true;
-
- } else if (node instanceof PhiNode) {
- /* The inputs of phi functions are filled manually when the end nodes are processed. */
- assert edges.type() == Edges.Type.Inputs;
- assert index == edges.getCount() - 1 : "PhiNode has one variable size input (the values)";
- if (decode) {
- /* The values must not be null, so initialize with an empty list. */
- edges.initializeList(node, index, new NodeInputList<>(node));
- }
- return true;
-
- }
- return false;
- }
-
protected Node lookupNode(LoopScope loopScope, int nodeOrderId) {
return loopScope.createdNodes[nodeOrderId];
}
@@ -1236,11 +1287,11 @@
* @param methodScope The current method.
*/
protected void cleanupGraph(MethodScope methodScope) {
- assert verifyEdges(methodScope);
+ assert verifyEdges();
}
- protected boolean verifyEdges(MethodScope methodScope) {
- for (Node node : methodScope.graph.getNodes()) {
+ protected boolean verifyEdges() {
+ for (Node node : graph.getNodes()) {
assert node.isAlive();
for (Node i : node.inputs()) {
assert i.isAlive();
@@ -1278,7 +1329,7 @@
* The ends, i.e., the source of backward branches. The {@link EndNode#successors successor}
* is the {@link #header loop header}.
*/
- List<EndNode> ends = new ArrayList<>();
+ List<EndNode> ends = new ArrayList<>(2);
/**
* Exits of the loop. The successor is a {@link MergeNode} marked in
* {@link MethodScope#loopExplosionMerges}.
@@ -1291,20 +1342,20 @@
boolean irreducible;
}
+ private final StructuredGraph graph;
private final MethodScope methodScope;
- private final FixedNode startInstruction;
private Loop irreducibleLoopHandler;
private IntegerSwitchNode irreducibleLoopSwitch;
- protected LoopDetector(MethodScope methodScope, FixedNode startInstruction) {
+ protected LoopDetector(StructuredGraph graph, MethodScope methodScope) {
+ this.graph = graph;
this.methodScope = methodScope;
- this.startInstruction = startInstruction;
}
@Override
public void run() {
- Debug.dump(Debug.VERBOSE_LOG_LEVEL, methodScope.graph, "Before loop detection");
+ Debug.dump(Debug.DETAILED_LEVEL, graph, "Before loop detection");
List<Loop> orderedLoops = findLoops();
assert orderedLoops.get(orderedLoops.size() - 1) == irreducibleLoopHandler : "outermost loop must be the last element in the list";
@@ -1327,11 +1378,11 @@
} else {
insertLoopNodes(loop);
}
- Debug.dump(Debug.VERBOSE_LOG_LEVEL, methodScope.graph, "After handling of loop %s", loop.header);
+ Debug.dump(Debug.DETAILED_LEVEL, graph, "After handling of loop %s", loop.header);
}
logIrreducibleLoops();
- Debug.dump(Debug.VERBOSE_LOG_LEVEL, methodScope.graph, "After loop detection");
+ Debug.dump(Debug.DETAILED_LEVEL, graph, "After loop detection");
}
private List<Loop> findLoops() {
@@ -1346,11 +1397,11 @@
*/
irreducibleLoopHandler = findOrCreateLoop(unorderedLoops, methodScope.loopExplosionHead);
- NodeBitMap visited = methodScope.graph.createNodeBitMap();
- NodeBitMap active = methodScope.graph.createNodeBitMap();
+ NodeBitMap visited = graph.createNodeBitMap();
+ NodeBitMap active = graph.createNodeBitMap();
Deque<Node> stack = new ArrayDeque<>();
- visited.mark(startInstruction);
- stack.push(startInstruction);
+ visited.mark(methodScope.loopExplosionHead);
+ stack.push(methodScope.loopExplosionHead);
while (!stack.isEmpty()) {
Node current = stack.peek();
@@ -1421,7 +1472,7 @@
*/
List<Node> possibleExits = new ArrayList<>();
- NodeBitMap visited = methodScope.graph.createNodeBitMap();
+ NodeBitMap visited = graph.createNodeBitMap();
Deque<Node> stack = new ArrayDeque<>();
for (EndNode loopEnd : loop.ends) {
stack.push(loopEnd);
@@ -1433,7 +1484,7 @@
if (current == loop.header) {
continue;
}
- if (!methodScope.graph.isNew(methodScope.methodStartMark, current)) {
+ if (!graph.isNew(methodScope.methodStartMark, current)) {
/*
* The current node is before the method that contains the exploded loop. The loop
* must have a second entry point, i.e., it is an irreducible loop.
@@ -1498,7 +1549,6 @@
* necessary into a loop because it computes loop information based on bytecodes, before the
* actual parsing.
*/
-
for (Node succ : possibleExits) {
if (!visited.contains(succ)) {
stack.push(succ);
@@ -1541,8 +1591,8 @@
FrameState stateAfter = merge.stateAfter().duplicate();
FixedNode afterMerge = merge.next();
merge.setNext(null);
- EndNode preLoopEnd = methodScope.graph.add(new EndNode());
- LoopBeginNode loopBegin = methodScope.graph.add(new LoopBeginNode());
+ EndNode preLoopEnd = graph.add(new EndNode());
+ LoopBeginNode loopBegin = graph.add(new LoopBeginNode());
merge.setNext(preLoopEnd);
/* Add the single non-loop predecessor of the loop header. */
@@ -1559,7 +1609,7 @@
List<PhiNode> loopBeginPhis = new ArrayList<>(mergePhis.size());
for (int i = 0; i < mergePhis.size(); i++) {
PhiNode mergePhi = mergePhis.get(i);
- PhiNode loopBeginPhi = methodScope.graph.addWithoutUnique(new ValuePhiNode(mergePhi.stamp(), loopBegin));
+ PhiNode loopBeginPhi = graph.addWithoutUnique(new ValuePhiNode(mergePhi.stamp(), loopBegin));
mergePhi.replaceAtUsages(loopBeginPhi);
/*
* The first input of the new phi function is the original phi function, for the one
@@ -1577,7 +1627,7 @@
}
merge.removeEnd(endNode);
- LoopEndNode loopEnd = methodScope.graph.add(new LoopEndNode(loopBegin));
+ LoopEndNode loopEnd = graph.add(new LoopEndNode(loopBegin));
endNode.replaceAndDelete(loopEnd);
}
@@ -1589,7 +1639,7 @@
AbstractMergeNode loopExplosionMerge = exit.merge();
assert methodScope.loopExplosionMerges.contains(loopExplosionMerge);
- LoopExitNode loopExit = methodScope.graph.add(new LoopExitNode(loopBegin));
+ LoopExitNode loopExit = graph.add(new LoopExitNode(loopBegin));
exit.replaceAtPredecessor(loopExit);
loopExit.setNext(exit);
assignLoopExitState(loopExit, loopExplosionMerge, exit);
@@ -1630,7 +1680,7 @@
realValue = ProxyPlaceholder.unwrap(value);
}
- if (realValue == null || realValue.isConstant() || loopBeginValues.contains(realValue) || !methodScope.graph.isNew(methodScope.methodStartMark, realValue)) {
+ if (realValue == null || realValue.isConstant() || loopBeginValues.contains(realValue) || !graph.isNew(methodScope.methodStartMark, realValue)) {
newValues.add(realValue);
} else {
/*
@@ -1641,7 +1691,7 @@
"Value flowing out of loop, but we are not prepared to insert a ProxyNode");
ProxyPlaceholder proxyPlaceholder = (ProxyPlaceholder) value;
- ValueProxyNode proxy = ProxyNode.forValue(proxyPlaceholder.value, loopExit, methodScope.graph);
+ ValueProxyNode proxy = ProxyNode.forValue(proxyPlaceholder.value, loopExit, graph);
proxyPlaceholder.setValue(proxy);
newValues.add(proxy);
}
@@ -1651,7 +1701,7 @@
oldState.duringCall(), oldState.monitorIds(), oldState.virtualObjectMappings());
assert loopExit.stateAfter() == null;
- loopExit.setStateAfter(methodScope.graph.add(newState));
+ loopExit.setStateAfter(graph.add(newState));
}
/**
@@ -1722,7 +1772,7 @@
assert irreducibleLoopHandler.header.phis().isEmpty();
/* The new phi function for the loop variable. */
- loopVariablePhi = methodScope.graph.addWithoutUnique(new ValuePhiNode(explosionHeadValue.stamp().unrestricted(), irreducibleLoopHandler.header));
+ loopVariablePhi = graph.addWithoutUnique(new ValuePhiNode(explosionHeadValue.stamp().unrestricted(), irreducibleLoopHandler.header));
for (int i = 0; i < irreducibleLoopHandler.header.phiPredecessorCount(); i++) {
loopVariablePhi.addInput(explosionHeadValue);
}
@@ -1732,7 +1782,7 @@
* to the old FrameState: the loop variable is replaced with the phi function.
*/
FrameState oldFrameState = explosionHeadState;
- List<ValueNode> newFrameStateValues = new ArrayList<>();
+ List<ValueNode> newFrameStateValues = new ArrayList<>(explosionHeadValues.size());
for (int i = 0; i < explosionHeadValues.size(); i++) {
if (i == loopVariableIndex) {
newFrameStateValues.add(loopVariablePhi);
@@ -1740,7 +1790,8 @@
newFrameStateValues.add(explosionHeadValues.get(i));
}
}
- FrameState newFrameState = methodScope.graph.add(
+
+ FrameState newFrameState = graph.add(
new FrameState(oldFrameState.outerFrameState(), oldFrameState.getCode(), oldFrameState.bci, newFrameStateValues, oldFrameState.localsSize(),
oldFrameState.stackSize(), oldFrameState.rethrowException(), oldFrameState.duringCall(), oldFrameState.monitorIds(),
oldFrameState.virtualObjectMappings()));
@@ -1752,7 +1803,7 @@
*/
FixedNode handlerNext = irreducibleLoopHandler.header.next();
irreducibleLoopHandler.header.setNext(null);
- BeginNode handlerBegin = methodScope.graph.add(new BeginNode());
+ BeginNode handlerBegin = graph.add(new BeginNode());
handlerBegin.setNext(handlerNext);
dispatchTable.put(asInt(explosionHeadValue), handlerBegin);
@@ -1760,8 +1811,8 @@
* We know that there will always be a matching key in the switch. But Graal always
* wants a default successor, so we build a dummy block that just deoptimizes.
*/
- unreachableDefaultSuccessor = methodScope.graph.add(new BeginNode());
- DeoptimizeNode deopt = methodScope.graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode));
+ unreachableDefaultSuccessor = graph.add(new BeginNode());
+ DeoptimizeNode deopt = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode));
unreachableDefaultSuccessor.setNext(deopt);
} else {
@@ -1796,8 +1847,8 @@
/* Insert our loop into the dispatch state machine. */
assert loop.header.phis().isEmpty();
- BeginNode dispatchBegin = methodScope.graph.add(new BeginNode());
- EndNode dispatchEnd = methodScope.graph.add(new EndNode());
+ BeginNode dispatchBegin = graph.add(new BeginNode());
+ EndNode dispatchEnd = graph.add(new EndNode());
dispatchBegin.setNext(dispatchEnd);
loop.header.addForwardEnd(dispatchEnd);
int intLoopValue = asInt(loopValue);
@@ -1813,7 +1864,7 @@
}
/* Build and insert the switch node. */
- irreducibleLoopSwitch = methodScope.graph.add(createSwitch(loopVariablePhi, dispatchTable, unreachableDefaultSuccessor));
+ irreducibleLoopSwitch = graph.add(createSwitch(loopVariablePhi, dispatchTable, unreachableDefaultSuccessor));
irreducibleLoopHandler.header.setNext(irreducibleLoopSwitch);
}
@@ -1859,14 +1910,14 @@
@SuppressWarnings("try")
private void logIrreducibleLoops() {
try (Debug.Scope s = Debug.scope("IrreducibleLoops")) {
- if (Debug.isLogEnabled(Debug.BASIC_LOG_LEVEL) && irreducibleLoopSwitch != null) {
+ if (Debug.isLogEnabled(Debug.BASIC_LEVEL) && irreducibleLoopSwitch != null) {
StringBuilder msg = new StringBuilder("Inserted state machine to remove irreducible loops. Dispatching to the following states: ");
String sep = "";
for (int i = 0; i < irreducibleLoopSwitch.keyCount(); i++) {
msg.append(sep).append(irreducibleLoopSwitch.keyAt(i).asInt());
sep = ", ";
}
- Debug.log(Debug.BASIC_LOG_LEVEL, "%s", msg);
+ Debug.log(Debug.BASIC_LEVEL, "%s", msg);
}
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java Thu Apr 06 23:01:27 2017 +0000
@@ -67,10 +67,11 @@
* encoding-local.
*
* The encoded graph has the following structure: First, all nodes and their edges are serialized.
- * The start offset of every node is then known. The raw node data is followed by a "table of
- * contents" that lists the start offset for every node.
+ * The start offset of every node is then known. The raw node data is followed by metadata, i.e.,
+ * the maximum fixed node order id and a "table of contents" that lists the start offset for every
+ * node.
*
- * The beginning of that table of contents is the return value of {@link #encode} and stored in
+ * The beginning of this metadata is the return value of {@link #encode} and stored in
* {@link EncodedGraph#getStartOffset()}. The order of nodes in the table of contents is the
* {@link NodeOrder#orderIds orderId} of a node. Note that the orderId is not the regular node id
* that every Graal graph node gets assigned. The orderId is computed and used just for encoding and
@@ -85,8 +86,8 @@
* <pre>
* struct Node {
* unsigned typeId
+ * unsigned[] inputOrderIds
* signed[] properties
- * unsigned[] inputOrderIds
* unsigned[] successorOrderIds
* }
* </pre>
@@ -168,9 +169,8 @@
*/
public void prepare(StructuredGraph graph) {
for (Node node : graph.getNodes()) {
- nodeClasses.addObject(node.getNodeClass());
-
- NodeClass<?> nodeClass = node.getNodeClass();
+ NodeClass<? extends Node> nodeClass = node.getNodeClass();
+ nodeClasses.addObject(nodeClass);
objects.addObject(node.getNodeSourcePosition());
for (int i = 0; i < nodeClass.getData().getCount(); i++) {
if (!nodeClass.getData().getType(i).isPrimitive()) {
@@ -223,8 +223,8 @@
/* Write out the type, properties, and edges. */
NodeClass<?> nodeClass = node.getNodeClass();
writer.putUV(nodeClasses.getIndex(nodeClass));
+ writeEdges(node, nodeClass.getEdges(Edges.Type.Inputs), nodeOrder);
writeProperties(node, nodeClass.getData());
- writeEdges(node, nodeClass.getEdges(Edges.Type.Inputs), nodeOrder);
writeEdges(node, nodeClass.getEdges(Edges.Type.Successors), nodeOrder);
/* Special handling for some nodes that require additional information for decoding. */
@@ -276,18 +276,23 @@
}
}
- /* Write out the table of contents with the start offset for all nodes. */
- int nodeTableStart = TypeConversion.asS4(writer.getBytesWritten());
+ /*
+ * Write out the metadata (maximum fixed node order id and the table of contents with the
+ * start offset for all nodes).
+ */
+ int metadataStart = TypeConversion.asS4(writer.getBytesWritten());
+ writer.putUV(nodeOrder.maxFixedNodeOrderId);
writer.putUV(nodeCount);
for (int i = 0; i < nodeCount; i++) {
assert i == NULL_ORDER_ID || i == START_NODE_ORDER_ID || nodeStartOffsets[i] > 0;
- writer.putUV(nodeTableStart - nodeStartOffsets[i]);
+ writer.putUV(metadataStart - nodeStartOffsets[i]);
}
/* Check that the decoding of the encode graph is the same as the input. */
- assert verifyEncoding(graph, new EncodedGraph(getEncoding(), nodeTableStart, getObjects(), getNodeClasses(), graph.getAssumptions(), graph.getMethods()), architecture);
+ assert verifyEncoding(graph, new EncodedGraph(getEncoding(), metadataStart, getObjects(), getNodeClasses(), graph.getAssumptions(), graph.getMethods()),
+ architecture);
- return nodeTableStart;
+ return metadataStart;
}
public byte[] getEncoding() {
@@ -297,6 +302,7 @@
static class NodeOrder {
protected final NodeMap<Integer> orderIds;
protected int nextOrderId;
+ protected int maxFixedNodeOrderId;
NodeOrder(StructuredGraph graph) {
this.orderIds = new NodeMap<>(graph);
@@ -337,6 +343,7 @@
}
} while (current != null);
+ maxFixedNodeOrderId = nextOrderId - 1;
for (Node node : graph.getNodes()) {
assert (node instanceof FixedNode) == (orderIds.get(node) != null) : "all fixed nodes must be ordered: " + node;
add(node);
@@ -365,6 +372,11 @@
}
protected void writeEdges(Node node, Edges edges, NodeOrder nodeOrder) {
+ if (node instanceof PhiNode) {
+ /* Edges are not needed for decoding, so we must not write it. */
+ return;
+ }
+
for (int idx = 0; idx < edges.getDirectCount(); idx++) {
if (GraphDecoder.skipDirectEdge(node, edges, idx)) {
/* Edge is not needed for decoding, so we must not write it. */
@@ -373,21 +385,23 @@
Node edge = Edges.getNode(node, edges.getOffsets(), idx);
writeOrderId(edge, nodeOrder);
}
- for (int idx = edges.getDirectCount(); idx < edges.getCount(); idx++) {
- if (GraphDecoder.skipIndirectEdge(node, edges, idx, false)) {
- /* Edge is not needed for decoding, so we must not write it. */
- continue;
- }
- NodeList<Node> edgeList = Edges.getNodeList(node, edges.getOffsets(), idx);
- if (edgeList == null) {
- writer.putSV(-1);
- } else {
- writer.putSV(edgeList.size());
- for (Node edge : edgeList) {
- writeOrderId(edge, nodeOrder);
+
+ if (node instanceof AbstractMergeNode && edges.type() == Edges.Type.Inputs) {
+ /* The ends of merge nodes are decoded manually when the ends are processed. */
+ } else {
+ for (int idx = edges.getDirectCount(); idx < edges.getCount(); idx++) {
+ NodeList<Node> edgeList = Edges.getNodeList(node, edges.getOffsets(), idx);
+ if (edgeList == null) {
+ writer.putSV(-1);
+ } else {
+ writer.putSV(edgeList.size());
+ for (Node edge : edgeList) {
+ writeOrderId(edge, nodeOrder);
+ }
}
}
}
+
}
protected void writeOrderId(Node node, NodeOrder nodeOrder) {
@@ -405,16 +419,16 @@
@SuppressWarnings("try")
public static boolean verifyEncoding(StructuredGraph originalGraph, EncodedGraph encodedGraph, Architecture architecture) {
StructuredGraph decodedGraph = new StructuredGraph.Builder(originalGraph.getOptions(), AllowAssumptions.YES).method(originalGraph.method()).build();
- GraphDecoder decoder = new GraphDecoder(architecture);
- decoder.decode(decodedGraph, encodedGraph);
+ GraphDecoder decoder = new GraphDecoder(architecture, decodedGraph);
+ decoder.decode(encodedGraph);
decodedGraph.verify();
try {
GraphComparison.verifyGraphsEqual(originalGraph, decodedGraph);
} catch (Throwable ex) {
try (Debug.Scope scope = Debug.scope("GraphEncoder")) {
- Debug.dump(Debug.INFO_LOG_LEVEL, originalGraph, "Original Graph");
- Debug.dump(Debug.INFO_LOG_LEVEL, decodedGraph, "Decoded Graph");
+ Debug.forceDump(originalGraph, "Original Graph");
+ Debug.forceDump(decodedGraph, "Decoded Graph");
}
throw ex;
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardedValueNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardedValueNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -87,7 +87,7 @@
if (stamp().equals(object().stamp())) {
return object();
} else {
- return new PiNode(object(), stamp());
+ return PiNode.create(object(), stamp());
}
}
return this;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -316,7 +316,10 @@
FixedWithNextNode falseNext = (FixedWithNextNode) falseSucc.next();
NodeClass<?> nodeClass = trueNext.getNodeClass();
if (trueNext.getClass() == falseNext.getClass()) {
- if (nodeClass.equalInputs(trueNext, falseNext) && trueNext.valueEquals(falseNext)) {
+ if (trueNext instanceof AbstractBeginNode) {
+ // Cannot do this optimization for begin nodes, because it could
+ // move guards above the if that need to stay below a branch.
+ } else if (nodeClass.equalInputs(trueNext, falseNext) && trueNext.valueEquals(falseNext)) {
falseNext.replaceAtUsages(trueNext);
graph().removeFixed(falseNext);
GraphUtil.unlinkFixedNode(trueNext);
@@ -600,7 +603,7 @@
protected void removeThroughFalseBranch(SimplifierTool tool) {
AbstractBeginNode trueBegin = trueSuccessor();
- graph().removeSplitPropagate(this, trueBegin, tool);
+ graph().removeSplitPropagate(this, trueBegin);
tool.addToWorkList(trueBegin);
if (condition() != null) {
GraphUtil.tryKillUnused(condition());
@@ -772,9 +775,9 @@
transferProxies(trueSuccessor(), trueMerge);
transferProxies(falseSuccessor(), falseMerge);
- cleanupMerge(tool, merge);
- cleanupMerge(tool, trueMerge);
- cleanupMerge(tool, falseMerge);
+ cleanupMerge(merge);
+ cleanupMerge(trueMerge);
+ cleanupMerge(falseMerge);
return true;
}
@@ -869,10 +872,10 @@
}
}
- private void cleanupMerge(SimplifierTool tool, MergeNode merge) {
+ private void cleanupMerge(MergeNode merge) {
if (merge != null && merge.isAlive()) {
if (merge.forwardEndCount() == 0) {
- GraphUtil.killCFG(merge, tool);
+ GraphUtil.killCFG(merge);
} else if (merge.forwardEndCount() == 1) {
graph().reduceTrivialMerge(merge);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiArrayNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiArrayNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -26,7 +26,6 @@
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
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;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
@@ -69,12 +68,11 @@
* snippet.
*/
@NodeIntrinsic(Placeholder.class)
- public static native Object piArrayCast(Object object, int length);
+ public static native Object piArrayCastToSnippetReplaceeStamp(Object object, int length);
/**
- * A placeholder node in a snippet that will be replaced with an appropriate {@link PiArrayNode}
- * when the snippet is instantiated. Using a placeholder means that {@link PiArrayNode} never
- * needs to deal with {@link StampFactory#forNodeIntrinsic()} stamps.
+ * A placeholder node in a snippet that will be replaced with a {@link PiArrayNode} when the
+ * snippet is instantiated.
*/
@NodeInfo(cycles = CYCLES_0, size = SIZE_0)
public static class Placeholder extends PiNode.Placeholder {
@@ -88,8 +86,9 @@
}
@Override
- public PiNode getReplacement(Stamp stampForPi) {
- return graph().addOrUnique(new PiArrayNode(object(), length, stampForPi));
+ public void makeReplacement(Stamp snippetReplaceeStamp) {
+ PiArrayNode piArray = graph().addOrUnique(new PiArrayNode(object(), length, snippetReplaceeStamp));
+ replaceAndDelete(piArray);
}
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -25,7 +25,10 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
+import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
@@ -36,6 +39,7 @@
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.extended.GuardingNode;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import org.graalvm.compiler.nodes.memory.ReadNode;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
@@ -70,7 +74,6 @@
protected PiNode(NodeClass<? extends PiNode> c, ValueNode object, Stamp stamp, GuardingNode guard) {
super(c, stamp, guard);
- assert stamp != StampFactory.forNodeIntrinsic();
this.object = object;
this.piStamp = stamp;
assert piStamp.isCompatible(object.stamp()) : "Object stamp not compatible to piStamp";
@@ -93,6 +96,53 @@
this(object, StampFactory.object(exactType ? TypeReference.createExactTrusted(toType) : TypeReference.createWithoutAssumptions(toType), nonNull || StampTool.isPointerNonNull(object.stamp())));
}
+ public static ValueNode create(ValueNode object, Stamp stamp) {
+ ValueNode value = canonical(object, stamp, null);
+ if (value != null) {
+ return value;
+ }
+ return new PiNode(object, stamp);
+ }
+
+ public static ValueNode create(ValueNode object, Stamp stamp, ValueNode anchor) {
+ ValueNode value = canonical(object, stamp, (GuardingNode) anchor);
+ if (value != null) {
+ return value;
+ }
+ return new PiNode(object, stamp, anchor);
+ }
+
+ public static ValueNode create(ValueNode object, ValueNode anchor) {
+ Stamp stamp = AbstractPointerStamp.pointerNonNull(object.stamp());
+ ValueNode value = canonical(object, stamp, (GuardingNode) anchor);
+ if (value != null) {
+ return value;
+ }
+ return new PiNode(object, stamp, anchor);
+ }
+
+ @SuppressWarnings("unused")
+ public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode object, ValueNode anchor) {
+ Stamp stamp = AbstractPointerStamp.pointerNonNull(object.stamp());
+ ValueNode value = canonical(object, stamp, (GuardingNode) anchor);
+ if (value == null) {
+ value = new PiNode(object, stamp, anchor);
+ }
+ b.push(JavaKind.Object, b.recursiveAppend(value));
+ return true;
+ }
+
+ @SuppressWarnings("unused")
+ public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
+ Stamp stamp = StampFactory.object(exactType ? TypeReference.createExactTrusted(toType) : TypeReference.createWithoutAssumptions(toType), nonNull || StampTool.isPointerNonNull(object.stamp()));
+ ValueNode value = canonical(object, stamp, null);
+ if (value == null) {
+ value = new PiNode(object, stamp);
+ }
+ b.push(JavaKind.Object, b.recursiveAppend(value));
+ return true;
+ }
+
public final Stamp piStamp() {
return piStamp;
}
@@ -124,37 +174,32 @@
}
}
- @Override
- public Node canonical(CanonicalizerTool tool) {
+ public static ValueNode canonical(ValueNode object, Stamp stamp, GuardingNode guard) {
// Use most up to date stamp.
- Stamp computedStamp = computeStamp();
-
- ValueNode o = object();
+ Stamp computedStamp = stamp.improveWith(object.stamp());
// The pi node does not give any additional information => skip it.
- if (computedStamp.equals(o.stamp())) {
- return o;
+ if (computedStamp.equals(object.stamp())) {
+ return object;
}
- GuardingNode g = getGuard();
- if (g == null) {
-
+ if (guard == null) {
// Try to merge the pi node with a load node.
- if (o instanceof ReadNode) {
- ReadNode readNode = (ReadNode) o;
- readNode.setStamp(readNode.stamp().improveWith(this.piStamp));
+ if (object instanceof ReadNode) {
+ ReadNode readNode = (ReadNode) object;
+ readNode.setStamp(readNode.stamp().improveWith(stamp));
return readNode;
}
} else {
- for (Node n : g.asNode().usages()) {
+ for (Node n : guard.asNode().usages()) {
if (n instanceof PiNode) {
PiNode otherPi = (PiNode) n;
- if (o == otherPi.object() && computedStamp.equals(otherPi.stamp())) {
+ if (object == otherPi.object() && computedStamp.equals(otherPi.stamp())) {
/*
* Two PiNodes with the same guard and same result, so return the one with
* the more precise piStamp.
*/
- Stamp newStamp = piStamp.join(otherPi.piStamp);
+ Stamp newStamp = stamp.join(otherPi.piStamp);
if (newStamp.equals(otherPi.piStamp)) {
return otherPi;
}
@@ -162,6 +207,15 @@
}
}
}
+ return null;
+ }
+
+ @Override
+ public Node canonical(CanonicalizerTool tool) {
+ Node value = canonical(object(), stamp(), getGuard());
+ if (value != null) {
+ return value;
+ }
return this;
}
@@ -226,9 +280,8 @@
public static native Object piCast(Object object, @ConstantNodeParameter Class<?> toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull);
/**
- * A placeholder node in a snippet that will be replaced with an appropriate {@link PiNode} when
- * the snippet is instantiated. Using a placeholder means that {@link PiNode} never needs to
- * deal with {@link StampFactory#forNodeIntrinsic()} stamps.
+ * A placeholder node in a snippet that will be replaced with a {@link PiNode} when the snippet
+ * is instantiated.
*/
@NodeInfo(cycles = CYCLES_0, size = SIZE_0)
public static class Placeholder extends FloatingGuardedNode {
@@ -241,7 +294,7 @@
}
protected Placeholder(NodeClass<? extends Placeholder> c, ValueNode object) {
- super(c, StampFactory.forNodeIntrinsic(), null);
+ super(c, PlaceholderStamp.SINGLETON, null);
this.object = object;
}
@@ -250,12 +303,44 @@
}
/**
- * Gets a new {@link PiNode} that replaces this placeholder during snippet instantiation.
+ * Replaces this node with a {@link PiNode} during snippet instantiation.
*
* @param snippetReplaceeStamp the stamp of the node being replace by the snippet
*/
- public PiNode getReplacement(Stamp snippetReplaceeStamp) {
- return graph().addOrUnique(new PiNode(object(), snippetReplaceeStamp, null));
+ public void makeReplacement(Stamp snippetReplaceeStamp) {
+ ValueNode value = graph().maybeAddOrUnique(PiNode.create(object(), snippetReplaceeStamp, null));
+ replaceAndDelete(value);
+ }
+ }
+
+ /**
+ * A stamp for {@link Placeholder} nodes which are only used in snippets. It is replaced by an
+ * actual stamp when the snippet is instantiated.
+ */
+ public static final class PlaceholderStamp extends ObjectStamp {
+ private static final PlaceholderStamp SINGLETON = new PlaceholderStamp();
+
+ public static PlaceholderStamp singleton() {
+ return SINGLETON;
+ }
+
+ private PlaceholderStamp() {
+ 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 "PlaceholderStamp";
}
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java Thu Apr 06 23:01:27 2017 +0000
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.nodes;
+import static org.graalvm.compiler.nodeinfo.InputType.Guard;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED;
@@ -37,6 +38,9 @@
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.extended.GuardingNode;
import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
+import org.graalvm.compiler.nodes.java.ArrayLengthNode;
+import org.graalvm.compiler.nodes.java.LoadFieldNode;
+import org.graalvm.compiler.nodes.java.LoadIndexedNode;
import org.graalvm.compiler.nodes.spi.StampProvider;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.options.OptionValues;
@@ -59,6 +63,7 @@
protected final ConstantFieldProvider constantFieldProvider;
protected final StampProvider stampProvider;
protected final boolean canonicalizeReads;
+ protected final CanonicalizerTool canonicalizerTool;
protected class PECanonicalizerTool implements CanonicalizerTool {
@@ -113,7 +118,7 @@
}
}
- @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
+ @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED, allowedUsageTypes = {Guard})
static class CanonicalizeToNullNode extends FloatingNode implements Canonicalizable, GuardingNode {
public static final NodeClass<CanonicalizeToNullNode> TYPE = NodeClass.create(CanonicalizeToNullNode.class);
@@ -127,32 +132,30 @@
}
}
- public SimplifyingGraphDecoder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, StampProvider stampProvider,
- boolean canonicalizeReads, Architecture architecture) {
- super(architecture);
+ public SimplifyingGraphDecoder(Architecture architecture, StructuredGraph graph, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection,
+ ConstantFieldProvider constantFieldProvider, StampProvider stampProvider,
+ boolean canonicalizeReads) {
+ super(architecture, graph);
this.metaAccess = metaAccess;
this.constantReflection = constantReflection;
this.constantFieldProvider = constantFieldProvider;
this.stampProvider = stampProvider;
this.canonicalizeReads = canonicalizeReads;
+ this.canonicalizerTool = new PECanonicalizerTool(graph.getAssumptions(), graph.getOptions());
}
@Override
protected void cleanupGraph(MethodScope methodScope) {
- GraphUtil.normalizeLoops(methodScope.graph);
+ GraphUtil.normalizeLoops(graph);
super.cleanupGraph(methodScope);
- for (Node node : methodScope.graph.getNewNodes(methodScope.methodStartMark)) {
+ for (Node node : graph.getNewNodes(methodScope.methodStartMark)) {
if (node instanceof MergeNode) {
MergeNode mergeNode = (MergeNode) node;
if (mergeNode.forwardEndCount() == 1) {
- methodScope.graph.reduceTrivialMerge(mergeNode);
+ graph.reduceTrivialMerge(mergeNode);
}
- }
- }
-
- for (Node node : methodScope.graph.getNewNodes(methodScope.methodStartMark)) {
- if (node instanceof BeginNode || node instanceof KillingBeginNode) {
+ } else if (node instanceof BeginNode || node instanceof KillingBeginNode) {
if (!(node.predecessor() instanceof ControlSplitNode) && node.hasNoUsages()) {
GraphUtil.unlinkFixedNode((AbstractBeginNode) node);
node.safeDelete();
@@ -160,7 +163,7 @@
}
}
- for (Node node : methodScope.graph.getNewNodes(methodScope.methodStartMark)) {
+ for (Node node : graph.getNewNodes(methodScope.methodStartMark)) {
GraphUtil.tryKillUnused(node);
}
}
@@ -187,7 +190,32 @@
@Override
protected void handleFixedNode(MethodScope methodScope, LoopScope loopScope, int nodeOrderId, FixedNode node) {
- if (node instanceof IfNode) {
+ Node canonical = canonicalizeFixedNode(node);
+ if (canonical != node) {
+ handleCanonicalization(loopScope, nodeOrderId, node, canonical);
+ }
+ }
+
+ private Node canonicalizeFixedNode(FixedNode node) {
+ if (node instanceof LoadFieldNode) {
+ LoadFieldNode loadFieldNode = (LoadFieldNode) node;
+ return loadFieldNode.canonical(canonicalizerTool);
+ } else if (node instanceof FixedGuardNode) {
+ FixedGuardNode guard = (FixedGuardNode) node;
+ if (guard.getCondition() instanceof LogicConstantNode) {
+ LogicConstantNode condition = (LogicConstantNode) guard.getCondition();
+ if (condition.getValue() == guard.isNegated()) {
+ DeoptimizeNode deopt = new DeoptimizeNode(guard.getAction(), guard.getReason(), guard.getSpeculation());
+ if (guard.stateBefore() != null) {
+ deopt.setStateBefore(guard.stateBefore());
+ }
+ return deopt;
+ } else {
+ return null;
+ }
+ }
+ return node;
+ } else if (node instanceof IfNode) {
IfNode ifNode = (IfNode) node;
if (ifNode.condition() instanceof LogicNegationNode) {
ifNode.eliminateNegation();
@@ -197,73 +225,55 @@
AbstractBeginNode survivingSuccessor = ifNode.getSuccessor(condition);
AbstractBeginNode deadSuccessor = ifNode.getSuccessor(!condition);
- methodScope.graph.removeSplit(ifNode, survivingSuccessor);
+ graph.removeSplit(ifNode, survivingSuccessor);
assert deadSuccessor.next() == null : "must not be parsed yet";
deadSuccessor.safeDelete();
}
-
+ return node;
+ } else if (node instanceof LoadIndexedNode) {
+ LoadIndexedNode loadIndexedNode = (LoadIndexedNode) node;
+ return loadIndexedNode.canonical(canonicalizerTool);
+ } else if (node instanceof ArrayLengthNode) {
+ ArrayLengthNode arrayLengthNode = (ArrayLengthNode) node;
+ return arrayLengthNode.canonical(canonicalizerTool);
} else if (node instanceof IntegerSwitchNode && ((IntegerSwitchNode) node).value().isConstant()) {
IntegerSwitchNode switchNode = (IntegerSwitchNode) node;
int value = switchNode.value().asJavaConstant().asInt();
AbstractBeginNode survivingSuccessor = switchNode.successorAtKey(value);
List<Node> allSuccessors = switchNode.successors().snapshot();
- methodScope.graph.removeSplit(switchNode, survivingSuccessor);
+ graph.removeSplit(switchNode, survivingSuccessor);
for (Node successor : allSuccessors) {
if (successor != survivingSuccessor) {
assert ((AbstractBeginNode) successor).next() == null : "must not be parsed yet";
successor.safeDelete();
}
}
-
- } else if (node instanceof FixedGuardNode) {
- FixedGuardNode guard = (FixedGuardNode) node;
- if (guard.getCondition() instanceof LogicConstantNode) {
- LogicConstantNode condition = (LogicConstantNode) guard.getCondition();
- Node canonical;
- if (condition.getValue() == guard.isNegated()) {
- DeoptimizeNode deopt = new DeoptimizeNode(guard.getAction(), guard.getReason(), guard.getSpeculation());
- if (guard.stateBefore() != null) {
- deopt.setStateBefore(guard.stateBefore());
- }
- canonical = deopt;
- } else {
- /*
- * The guard is unnecessary, but we cannot remove the node completely yet
- * because there might be nodes that use it as a guard input. Therefore, we
- * replace it with a more lightweight node (which is floating and has no
- * inputs).
- */
- canonical = new CanonicalizeToNullNode(node.stamp);
- }
- handleCanonicalization(methodScope, loopScope, nodeOrderId, node, canonical);
- }
-
+ return node;
} else if (node instanceof Canonicalizable) {
- Node canonical = ((Canonicalizable) node).canonical(new PECanonicalizerTool(methodScope.graph.getAssumptions(), methodScope.graph.getOptions()));
- if (canonical != node) {
- handleCanonicalization(methodScope, loopScope, nodeOrderId, node, canonical);
- }
+ return ((Canonicalizable) node).canonical(canonicalizerTool);
+ } else {
+ return node;
}
}
- private void handleCanonicalization(MethodScope methodScope, LoopScope loopScope, int nodeOrderId, FixedNode node, Node c) {
- Node canonical = c;
+ private static Node canonicalizeFixedNodeToNull(FixedNode node) {
+ /*
+ * When a node is unnecessary, we must not remove it right away because there might be nodes
+ * that use it as a guard input. Therefore, we replace it with a more lightweight node
+ * (which is floating and has no inputs).
+ */
+ return new CanonicalizeToNullNode(node.stamp);
+ }
- if (canonical == null) {
- /*
- * This is a possible return value of canonicalization. However, we might need to add
- * additional usages later on for which we need a node. Therefore, we just do nothing
- * and leave the node in place.
- */
- return;
- }
-
+ private void handleCanonicalization(LoopScope loopScope, int nodeOrderId, FixedNode node, Node c) {
+ assert c != node : "unnecessary call";
+ Node canonical = c == null ? canonicalizeFixedNodeToNull(node) : c;
if (!canonical.isAlive()) {
assert !canonical.isDeleted();
- canonical = methodScope.graph.addOrUniqueWithInputs(canonical);
+ canonical = graph.addOrUniqueWithInputs(canonical);
if (canonical instanceof FixedWithNextNode) {
- methodScope.graph.addBeforeFixed(node, (FixedWithNextNode) canonical);
+ graph.addBeforeFixed(node, (FixedWithNextNode) canonical);
} else if (canonical instanceof ControlSinkNode) {
FixedWithNextNode predecessor = (FixedWithNextNode) node.predecessor();
predecessor.setNext((ControlSinkNode) canonical);
@@ -291,7 +301,7 @@
((ValueNode) node).inferStamp();
}
if (node instanceof Canonicalizable) {
- Node canonical = ((Canonicalizable) node).canonical(new PECanonicalizerTool(methodScope.graph.getAssumptions(), methodScope.graph.getOptions()));
+ Node canonical = ((Canonicalizable) node).canonical(canonicalizerTool);
if (canonical == null) {
/*
* This is a possible return value of canonicalization. However, we might need to
@@ -301,10 +311,9 @@
} else if (canonical != node) {
if (!canonical.isAlive()) {
assert !canonical.isDeleted();
- canonical = methodScope.graph.addOrUniqueWithInputs(canonical);
+ canonical = graph.addOrUniqueWithInputs(canonical);
}
assert node.hasNoUsages();
- // methodScope.graph.replaceFloating((FloatingNode) node, canonical);
return canonical;
}
}
@@ -317,6 +326,6 @@
* In contrast to the base class implementation, we do not need to exactly reproduce the
* encoded graph. Since we do canonicalization, we also want nodes to be unique.
*/
- return methodScope.graph.addOrUnique(node);
+ return graph.addOrUnique(node);
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Thu Apr 06 23:01:27 2017 +0000
@@ -37,7 +37,6 @@
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeMap;
-import org.graalvm.compiler.graph.spi.SimplifierTool;
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.cfg.Block;
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
@@ -553,12 +552,8 @@
node.safeDelete();
}
+ @SuppressWarnings("static-method")
public void removeSplitPropagate(ControlSplitNode node, AbstractBeginNode survivingSuccessor) {
- removeSplitPropagate(node, survivingSuccessor, null);
- }
-
- @SuppressWarnings("static-method")
- public void removeSplitPropagate(ControlSplitNode node, AbstractBeginNode survivingSuccessor, SimplifierTool tool) {
assert node != null;
assert node.hasNoUsages();
assert survivingSuccessor != null;
@@ -569,7 +564,7 @@
for (Node successor : snapshot) {
if (successor != null && successor.isAlive()) {
if (successor != survivingSuccessor) {
- GraphUtil.killCFG((FixedNode) successor, tool);
+ GraphUtil.killCFG((FixedNode) successor);
}
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AddNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AddNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -57,28 +57,16 @@
ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp);
if (tryConstantFold != null) {
return tryConstantFold;
+ }
+ if (x.isConstant() && !y.isConstant()) {
+ return canonical(null, op, y, x);
} else {
- return new AddNode(x, y).maybeCommuteInputs();
+ return canonical(null, op, x, y);
}
}
- @Override
- public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
- ValueNode ret = super.canonical(tool, forX, forY);
- if (ret != this) {
- return ret;
- }
-
- if (forX.isConstant() && !forY.isConstant()) {
- // we try to swap and canonicalize
- ValueNode improvement = canonical(tool, forY, forX);
- if (improvement != this) {
- return improvement;
- }
- // if this fails we only swap
- return new AddNode(forY, forX);
- }
- BinaryOp<Add> op = getOp(forX, forY);
+ private static ValueNode canonical(AddNode addNode, BinaryOp<Add> op, ValueNode forX, ValueNode forY) {
+ AddNode self = addNode;
boolean associative = op.isAssociative();
if (associative) {
if (forX instanceof SubNode) {
@@ -101,10 +89,10 @@
if (op.isNeutral(c)) {
return forX;
}
- if (associative) {
+ if (associative && self != null) {
// canonicalize expressions like "(a + 1) + 2"
- ValueNode reassociated = reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
- if (reassociated != this) {
+ ValueNode reassociated = reassociate(self, ValueNode.isConstantPredicate(), forX, forY);
+ if (reassociated != self) {
return reassociated;
}
}
@@ -114,7 +102,30 @@
} else if (forY instanceof NegateNode) {
return BinaryArithmeticNode.sub(forX, ((NegateNode) forY).getValue());
}
- return this;
+ if (self == null) {
+ self = (AddNode) new AddNode(forX, forY).maybeCommuteInputs();
+ }
+ return self;
+ }
+
+ @Override
+ public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+ ValueNode ret = super.canonical(tool, forX, forY);
+ if (ret != this) {
+ return ret;
+ }
+
+ if (forX.isConstant() && !forY.isConstant()) {
+ // we try to swap and canonicalize
+ ValueNode improvement = canonical(tool, forY, forX);
+ if (improvement != this) {
+ return improvement;
+ }
+ // if this fails we only swap
+ return new AddNode(forY, forX);
+ }
+ BinaryOp<Add> op = getOp(forX, forY);
+ return canonical(this, op, forX, forY);
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AndNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AndNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -57,9 +57,8 @@
ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp);
if (tryConstantFold != null) {
return tryConstantFold;
- } else {
- return new AndNode(x, y).maybeCommuteInputs();
}
+ return canonical(null, op, stamp, x, y);
}
@Override
@@ -69,6 +68,10 @@
return ret;
}
+ return canonical(this, getOp(forX, forY), stamp(), forX, forY);
+ }
+
+ private static ValueNode canonical(AndNode self, BinaryOp<And> op, Stamp stamp, ValueNode forX, ValueNode forY) {
if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
return forX;
}
@@ -77,15 +80,15 @@
}
if (forY.isConstant()) {
Constant c = forY.asConstant();
- if (getOp(forX, forY).isNeutral(c)) {
+ if (op.isNeutral(c)) {
return forX;
}
if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) {
long rawY = ((PrimitiveConstant) c).asLong();
- long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp()));
+ long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp));
if ((rawY & mask) == 0) {
- return ConstantNode.forIntegerStamp(stamp(), 0);
+ return ConstantNode.forIntegerStamp(stamp, 0);
}
if (forX instanceof SignExtendNode) {
SignExtendNode ext = (SignExtendNode) forX;
@@ -100,9 +103,12 @@
}
}
- return reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
+ return reassociate(self != null ? self : (AndNode) new AndNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY);
}
- return this;
+ if (forX instanceof NotNode && forY instanceof NotNode) {
+ return new NotNode(OrNode.create(((NotNode) forX).getValue(), ((NotNode) forY).getValue()));
+ }
+ return self != null ? self : new AndNode(forX, forY).maybeCommuteInputs();
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -44,6 +44,7 @@
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.PrimitiveConstant;
@NodeInfo(cycles = CYCLES_1)
public abstract class CompareNode extends BinaryOpLogicNode implements Canonicalizable.Binary<ValueNode> {
@@ -151,12 +152,19 @@
}
public static LogicNode tryConstantFold(Condition condition, ValueNode forX, ValueNode forY, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) {
- if (forX.isConstant() && forY.isConstant() && constantReflection != null) {
+ if (forX.isConstant() && forY.isConstant() && (constantReflection != null || forX.asConstant() instanceof PrimitiveConstant)) {
return LogicConstantNode.forBoolean(condition.foldCondition(forX.asConstant(), forY.asConstant(), constantReflection, unorderedIsTrue));
}
return null;
}
+ public static LogicNode tryConstantFoldPrimitive(Condition condition, ValueNode forX, ValueNode forY, boolean unorderedIsTrue) {
+ if (forX.asConstant() instanceof PrimitiveConstant && forY.asConstant() instanceof PrimitiveConstant) {
+ return LogicConstantNode.forBoolean(condition.foldCondition((PrimitiveConstant) forX.asConstant(), (PrimitiveConstant) forY.asConstant(), unorderedIsTrue));
+ }
+ return null;
+ }
+
/**
* Does this operation represent an identity check such that for x == y, x is exactly the same
* thing as y. This is generally true except for some floating point comparisons.
@@ -221,7 +229,7 @@
public static LogicNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) {
LogicNode result = createCompareNode(condition, x, y, constantReflection);
- return (result.graph() == null ? graph.unique(result) : result);
+ return (result.graph() == null ? graph.addOrUniqueWithInputs(result) : result);
}
public static LogicNode createCompareNode(Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) {
@@ -237,15 +245,15 @@
comparison = PointerEqualsNode.create(x, y);
} else {
assert x.getStackKind().isNumericInteger();
- comparison = IntegerEqualsNode.create(x, y, constantReflection);
+ comparison = IntegerEqualsNode.create(x, y);
}
} else if (condition == Condition.LT) {
assert x.getStackKind().isNumericInteger();
- comparison = IntegerLessThanNode.create(x, y, constantReflection);
+ comparison = IntegerLessThanNode.create(x, y);
} else {
assert condition == Condition.BT;
assert x.getStackKind().isNumericInteger();
- comparison = IntegerBelowNode.create(x, y, constantReflection);
+ comparison = IntegerBelowNode.create(x, y);
}
return comparison;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -83,6 +83,10 @@
if (synonym != null) {
return synonym;
}
+ ValueNode result = canonicalizeConditional(condition, trueValue, falseValue, trueValue.stamp().meet(falseValue.stamp()));
+ if (result != null) {
+ return result;
+ }
return new ConditionalNode(condition, trueValue, falseValue);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/DivNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/DivNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -58,9 +58,8 @@
ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp);
if (tryConstantFold != null) {
return tryConstantFold;
- } else {
- return new DivNode(x, y);
}
+ return canonical(null, op, x, y);
}
@Override
@@ -70,9 +69,13 @@
return ret;
}
+ return canonical(this, getOp(forX, forY), forX, forY);
+ }
+
+ private static ValueNode canonical(DivNode self, BinaryOp<Div> op, ValueNode forX, ValueNode forY) {
if (forY.isConstant()) {
Constant c = forY.asConstant();
- if (getOp(forX, forY).isNeutral(c)) {
+ if (op.isNeutral(c)) {
return forX;
}
if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) {
@@ -88,14 +91,14 @@
}
if (divResult != null) {
if (signFlip) {
- return new NegateNode(divResult);
+ return NegateNode.create(divResult);
} else {
return divResult;
}
}
}
}
- return this;
+ return self != null ? self : new DivNode(forX, forY);
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -37,7 +37,6 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.util.GraphUtil;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.TriState;
@NodeInfo(shortName = "==", cycles = NodeCycles.CYCLES_3)
@@ -50,8 +49,8 @@
assert x.stamp().isCompatible(y.stamp());
}
- public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) {
- LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, constantReflection, false);
+ public static LogicNode create(ValueNode x, ValueNode y) {
+ LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.EQ, x, y, false);
if (result != null) {
return result;
} else {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -36,7 +36,6 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.util.GraphUtil;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.TriState;
@NodeInfo(shortName = "<", cycles = NodeCycles.CYCLES_3)
@@ -49,8 +48,8 @@
assert x.stamp().isCompatible(y.stamp());
}
- public static LogicNode create(ValueNode x, ValueNode y, boolean unorderedIsTrue, ConstantReflectionProvider constantReflection) {
- LogicNode result = CompareNode.tryConstantFold(Condition.LT, x, y, constantReflection, unorderedIsTrue);
+ public static LogicNode create(ValueNode x, ValueNode y, boolean unorderedIsTrue) {
+ LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.LT, x, y, unorderedIsTrue);
if (result != null) {
return result;
} else {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -32,7 +32,6 @@
import org.graalvm.compiler.nodes.ValueNode;
import jdk.vm.ci.code.CodeUtil;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
@NodeInfo(shortName = "|<|")
public final class IntegerBelowNode extends IntegerLowerThanNode {
@@ -45,8 +44,8 @@
assert y.stamp() instanceof IntegerStamp;
}
- public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) {
- return OP.create(x, y, constantReflection);
+ public static LogicNode create(ValueNode x, ValueNode y) {
+ return OP.create(x, y);
}
@Override
@@ -108,7 +107,7 @@
}
@Override
- protected IntegerLowerThanNode create(ValueNode x, ValueNode y) {
+ protected IntegerLowerThanNode createNode(ValueNode x, ValueNode y) {
return new IntegerBelowNode(x, y);
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -40,7 +40,6 @@
import org.graalvm.compiler.nodes.util.GraphUtil;
import jdk.vm.ci.meta.Constant;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.PrimitiveConstant;
import jdk.vm.ci.meta.TriState;
@@ -55,8 +54,8 @@
assert !y.getStackKind().isNumericFloat() && y.getStackKind() != JavaKind.Object;
}
- public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) {
- LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, constantReflection, false);
+ public static LogicNode create(ValueNode x, ValueNode y) {
+ LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.EQ, x, y, false);
if (result != null) {
return result;
} else {
@@ -117,6 +116,29 @@
} else if (forX.stamp().alwaysDistinct(forY.stamp())) {
return LogicConstantNode.contradiction();
}
+ if (forX instanceof AddNode && forY instanceof AddNode) {
+ AddNode addX = (AddNode) forX;
+ AddNode addY = (AddNode) forY;
+ ValueNode v1 = null;
+ ValueNode v2 = null;
+ if (addX.getX() == addY.getX()) {
+ v1 = addX.getY();
+ v2 = addY.getY();
+ } else if (addX.getX() == addY.getY()) {
+ v1 = addX.getY();
+ v2 = addY.getX();
+ } else if (addX.getY() == addY.getX()) {
+ v1 = addX.getX();
+ v2 = addY.getY();
+ } else if (addX.getY() == addY.getY()) {
+ v1 = addX.getX();
+ v2 = addY.getX();
+ }
+ if (v1 != null) {
+ assert v2 != null;
+ return create(v1, v2);
+ }
+ }
return super.canonical(tool, forX, forY);
}
@@ -130,14 +152,14 @@
// nonConstant can only be 0 or 1 (respective -1), test against 0 instead of 1
// (respective -1) for a more canonical graph and also to allow for faster execution
// on specific platforms.
- return LogicNegationNode.create(IntegerEqualsNode.create(nonConstant, ConstantNode.forIntegerKind(nonConstant.getStackKind(), 0), null));
+ return LogicNegationNode.create(IntegerEqualsNode.create(nonConstant, ConstantNode.forIntegerKind(nonConstant.getStackKind(), 0)));
} else if (primitiveConstant.asLong() == 0) {
if (nonConstant instanceof AndNode) {
AndNode andNode = (AndNode) nonConstant;
return new IntegerTestNode(andNode.getX(), andNode.getY());
} else if (nonConstant instanceof SubNode) {
SubNode subNode = (SubNode) nonConstant;
- return IntegerEqualsNode.create(subNode.getX(), subNode.getY(), tool.getConstantReflection());
+ return IntegerEqualsNode.create(subNode.getX(), subNode.getY());
} else if (nonConstant instanceof ShiftNode && nonConstant.stamp() instanceof IntegerStamp) {
if (nonConstant instanceof LeftShiftNode) {
LeftShiftNode shift = (LeftShiftNode) nonConstant;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -31,15 +31,14 @@
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.graph.spi.CanonicalizerTool;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.ConstantNode;
+import org.graalvm.compiler.nodes.LogicNegationNode;
import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.ValueNode;
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.meta.Constant;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.PrimitiveConstant;
@@ -55,8 +54,8 @@
assert !y.getStackKind().isNumericFloat() && y.getStackKind() != JavaKind.Object;
}
- public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) {
- return OP.create(x, y, constantReflection);
+ public static LogicNode create(ValueNode x, ValueNode y) {
+ return OP.create(x, y);
}
@Override
@@ -91,79 +90,6 @@
}
@Override
- public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
- ValueNode result = super.canonical(tool, forX, forY);
- if (result != this) {
- return result;
- }
- if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) {
- if (IntegerStamp.sameSign((IntegerStamp) forX.stamp(), (IntegerStamp) forY.stamp())) {
- return new IntegerBelowNode(forX, forY);
- }
- }
- if (forY.isConstant() && forY.asConstant().isDefaultForKind() && forX instanceof SubNode) {
- // (x - y) < 0 when x - y is known not to underflow <=> x < y
- SubNode sub = (SubNode) forX;
- IntegerStamp xStamp = (IntegerStamp) sub.getX().stamp();
- IntegerStamp yStamp = (IntegerStamp) sub.getY().stamp();
- long minValue = CodeUtil.minValue(xStamp.getBits());
- long maxValue = CodeUtil.maxValue(xStamp.getBits());
-
- if (!subtractMayUnderflow(xStamp.lowerBound(), yStamp.upperBound(), minValue) && !subtractMayOverflow(xStamp.upperBound(), yStamp.lowerBound(), maxValue)) {
- return new IntegerLessThanNode(sub.getX(), sub.getY());
- }
- }
-
- int bits = ((IntegerStamp) getX().stamp()).getBits();
- assert ((IntegerStamp) getY().stamp()).getBits() == bits;
- long min = OP.minValue(bits);
- long xResidue = 0;
- ValueNode left = null;
- JavaConstant leftCst = null;
- if (forX instanceof AddNode) {
- AddNode xAdd = (AddNode) forX;
- if (xAdd.getY().isJavaConstant()) {
- long xCst = xAdd.getY().asJavaConstant().asLong();
- xResidue = xCst - min;
- left = xAdd.getX();
- }
- } else if (forX.isJavaConstant()) {
- leftCst = forX.asJavaConstant();
- }
- if (left != null || leftCst != null) {
- long yResidue = 0;
- ValueNode right = null;
- JavaConstant rightCst = null;
- if (forY instanceof AddNode) {
- AddNode yAdd = (AddNode) forY;
- if (yAdd.getY().isJavaConstant()) {
- long yCst = yAdd.getY().asJavaConstant().asLong();
- yResidue = yCst - min;
- right = yAdd.getX();
- }
- } else if (forY.isJavaConstant()) {
- rightCst = forY.asJavaConstant();
- }
- if (right != null || rightCst != null) {
- if ((xResidue == 0 && left != null) || (yResidue == 0 && right != null)) {
- if (left == null) {
- left = ConstantNode.forIntegerBits(bits, leftCst.asLong() - min);
- } else if (xResidue != 0) {
- left = AddNode.create(left, ConstantNode.forIntegerBits(bits, xResidue));
- }
- if (right == null) {
- right = ConstantNode.forIntegerBits(bits, rightCst.asLong() - min);
- } else if (yResidue != 0) {
- right = AddNode.create(right, ConstantNode.forIntegerBits(bits, yResidue));
- }
- return new IntegerBelowNode(left, right);
- }
- }
- }
- return this;
- }
-
- @Override
protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) {
if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) {
return new FloatLessThanNode(newX, newY, true);
@@ -176,12 +102,104 @@
public static class LessThanOp extends LowerOp {
@Override
+ protected LogicNode findSynonym(ValueNode forX, ValueNode forY) {
+ LogicNode result = super.findSynonym(forX, forY);
+ if (result != null) {
+ return result;
+ }
+ if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) {
+ if (IntegerStamp.sameSign((IntegerStamp) forX.stamp(), (IntegerStamp) forY.stamp())) {
+ return new IntegerBelowNode(forX, forY);
+ }
+ }
+ if (forY.isConstant() && forX instanceof SubNode) {
+ SubNode sub = (SubNode) forX;
+ ValueNode xx = null;
+ ValueNode yy = null;
+ boolean negate = false;
+ if (forY.asConstant().isDefaultForKind()) {
+ // (x - y) < 0 when x - y is known not to underflow <=> x < y
+ xx = sub.getX();
+ yy = sub.getY();
+ } else if (forY.isJavaConstant() && forY.asJavaConstant().asLong() == 1) {
+ // (x - y) < 1 when x - y is known not to underflow <=> !(y < x)
+ xx = sub.getY();
+ yy = sub.getX();
+ negate = true;
+ }
+ if (xx != null) {
+ assert yy != null;
+ IntegerStamp xStamp = (IntegerStamp) sub.getX().stamp();
+ IntegerStamp yStamp = (IntegerStamp) sub.getY().stamp();
+ long minValue = CodeUtil.minValue(xStamp.getBits());
+ long maxValue = CodeUtil.maxValue(xStamp.getBits());
+
+ if (!subtractMayUnderflow(xStamp.lowerBound(), yStamp.upperBound(), minValue) && !subtractMayOverflow(xStamp.upperBound(), yStamp.lowerBound(), maxValue)) {
+ LogicNode logic = new IntegerLessThanNode(xx, yy);
+ if (negate) {
+ logic = LogicNegationNode.create(logic);
+ }
+ return logic;
+ }
+ }
+ }
+
+ int bits = ((IntegerStamp) forX.stamp()).getBits();
+ assert ((IntegerStamp) forY.stamp()).getBits() == bits;
+ long min = OP.minValue(bits);
+ long xResidue = 0;
+ ValueNode left = null;
+ JavaConstant leftCst = null;
+ if (forX instanceof AddNode) {
+ AddNode xAdd = (AddNode) forX;
+ if (xAdd.getY().isJavaConstant()) {
+ long xCst = xAdd.getY().asJavaConstant().asLong();
+ xResidue = xCst - min;
+ left = xAdd.getX();
+ }
+ } else if (forX.isJavaConstant()) {
+ leftCst = forX.asJavaConstant();
+ }
+ if (left != null || leftCst != null) {
+ long yResidue = 0;
+ ValueNode right = null;
+ JavaConstant rightCst = null;
+ if (forY instanceof AddNode) {
+ AddNode yAdd = (AddNode) forY;
+ if (yAdd.getY().isJavaConstant()) {
+ long yCst = yAdd.getY().asJavaConstant().asLong();
+ yResidue = yCst - min;
+ right = yAdd.getX();
+ }
+ } else if (forY.isJavaConstant()) {
+ rightCst = forY.asJavaConstant();
+ }
+ if (right != null || rightCst != null) {
+ if ((xResidue == 0 && left != null) || (yResidue == 0 && right != null)) {
+ if (left == null) {
+ left = ConstantNode.forIntegerBits(bits, leftCst.asLong() - min);
+ } else if (xResidue != 0) {
+ left = AddNode.create(left, ConstantNode.forIntegerBits(bits, xResidue));
+ }
+ if (right == null) {
+ right = ConstantNode.forIntegerBits(bits, rightCst.asLong() - min);
+ } else if (yResidue != 0) {
+ right = AddNode.create(right, ConstantNode.forIntegerBits(bits, yResidue));
+ }
+ return new IntegerBelowNode(left, right);
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
protected Condition getCondition() {
return LT;
}
@Override
- protected IntegerLowerThanNode create(ValueNode x, ValueNode y) {
+ protected IntegerLowerThanNode createNode(ValueNode x, ValueNode y) {
return new IntegerLessThanNode(x, y);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -28,13 +28,13 @@
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.LogicConstantNode;
import org.graalvm.compiler.nodes.LogicNegationNode;
import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.util.GraphUtil;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.TriState;
/**
@@ -65,51 +65,9 @@
if (synonym != null) {
return synonym;
}
- if (forY.stamp() instanceof IntegerStamp) {
- IntegerStamp yStamp = (IntegerStamp) forY.stamp();
- if (forX.isConstant() && forX.asJavaConstant().asLong() == getOp().minValue(yStamp.getBits())) {
- // MIN < y is the same as y != MIN
- return LogicNegationNode.create(CompareNode.createCompareNode(Condition.EQ, forY, forX, tool.getConstantReflection()));
- }
- if (forY instanceof AddNode) {
- AddNode addNode = (AddNode) forY;
- ValueNode canonical = canonicalizeXLowerXPlusA(forX, addNode, false, true);
- if (canonical != null) {
- return canonical;
- }
- }
- if (forX instanceof AddNode) {
- AddNode addNode = (AddNode) forX;
- ValueNode canonical = canonicalizeXLowerXPlusA(forY, addNode, true, false);
- if (canonical != null) {
- return canonical;
- }
- }
- }
return this;
}
- private ValueNode canonicalizeXLowerXPlusA(ValueNode forX, AddNode addNode, boolean negated, boolean strict) {
- // x < x + a
- Stamp succeedingXStamp;
- if (addNode.getX() == forX && addNode.getY().stamp() instanceof IntegerStamp) {
- succeedingXStamp = getOp().getSucceedingStampForXLowerXPlusA(negated, strict, (IntegerStamp) addNode.getY().stamp());
- } else if (addNode.getY() == forX && addNode.getX().stamp() instanceof IntegerStamp) {
- succeedingXStamp = getOp().getSucceedingStampForXLowerXPlusA(negated, strict, (IntegerStamp) addNode.getX().stamp());
- } else {
- return null;
- }
- succeedingXStamp = forX.stamp().join(succeedingXStamp);
- if (succeedingXStamp.isEmpty()) {
- return LogicConstantNode.contradiction();
- }
- /*
- * since getSucceedingStampForXLowerXPlusA is only best effort,
- * succeedingXStamp.equals(xStamp) does not imply tautology
- */
- return null;
- }
-
@Override
public Stamp getSucceedingStampForX(boolean negated, Stamp xStampGeneric, Stamp yStampGeneric) {
return getSucceedingStampForX(negated, !negated, xStampGeneric, yStampGeneric, getX(), getY());
@@ -196,10 +154,10 @@
protected abstract Condition getCondition();
- protected abstract IntegerLowerThanNode create(ValueNode x, ValueNode y);
+ protected abstract IntegerLowerThanNode createNode(ValueNode x, ValueNode y);
- public LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) {
- LogicNode result = CompareNode.tryConstantFold(getCondition(), x, y, constantReflection, false);
+ public LogicNode create(ValueNode x, ValueNode y) {
+ LogicNode result = CompareNode.tryConstantFoldPrimitive(getCondition(), x, y, false);
if (result != null) {
return result;
} else {
@@ -207,7 +165,7 @@
if (result != null) {
return result;
}
- return create(x, y);
+ return createNode(x, y);
}
}
@@ -221,6 +179,73 @@
} else if (fold.isFalse()) {
return LogicConstantNode.contradiction();
}
+ if (forY.stamp() instanceof IntegerStamp) {
+ IntegerStamp yStamp = (IntegerStamp) forY.stamp();
+ int bits = yStamp.getBits();
+ if (forX.isJavaConstant() && !forY.isConstant()) {
+ // bring the constant on the right
+ long xValue = forX.asJavaConstant().asLong();
+ if (xValue != maxValue(bits)) {
+ // c < x <=> !(c >= x) <=> !(x <= c) <=> !(x < c + 1)
+ return LogicNegationNode.create(create(forY, ConstantNode.forIntegerStamp(yStamp, xValue + 1)));
+ }
+ }
+ if (forY.isJavaConstant()) {
+ long yValue = forY.asJavaConstant().asLong();
+ if (yValue == maxValue(bits)) {
+ // x < MAX <=> x != MAX
+ return LogicNegationNode.create(IntegerEqualsNode.create(forX, forY));
+ }
+ if (yValue == minValue(bits) + 1) {
+ // x < MIN + 1 <=> x <= MIN <=> x == MIN
+ return IntegerEqualsNode.create(forX, ConstantNode.forIntegerStamp(yStamp, minValue(bits)));
+ }
+ } else if (forY instanceof AddNode) {
+ AddNode addNode = (AddNode) forY;
+ LogicNode canonical = canonicalizeXLowerXPlusA(forX, addNode, false, true);
+ if (canonical != null) {
+ return canonical;
+ }
+ }
+ if (forX instanceof AddNode) {
+ AddNode addNode = (AddNode) forX;
+ LogicNode canonical = canonicalizeXLowerXPlusA(forY, addNode, true, false);
+ if (canonical != null) {
+ return canonical;
+ }
+ }
+ }
+ return null;
+ }
+
+ private LogicNode canonicalizeXLowerXPlusA(ValueNode forX, AddNode addNode, boolean mirrored, boolean strict) {
+ // x < x + a
+ IntegerStamp succeedingXStamp;
+ boolean exact;
+ if (addNode.getX() == forX && addNode.getY().stamp() instanceof IntegerStamp) {
+ IntegerStamp aStamp = (IntegerStamp) addNode.getY().stamp();
+ succeedingXStamp = getSucceedingStampForXLowerXPlusA(mirrored, strict, aStamp);
+ exact = aStamp.lowerBound() == aStamp.upperBound();
+ } else if (addNode.getY() == forX && addNode.getX().stamp() instanceof IntegerStamp) {
+ IntegerStamp aStamp = (IntegerStamp) addNode.getX().stamp();
+ succeedingXStamp = getSucceedingStampForXLowerXPlusA(mirrored, strict, aStamp);
+ exact = aStamp.lowerBound() == aStamp.upperBound();
+ } else {
+ return null;
+ }
+ if (succeedingXStamp.join(forX.stamp()).isEmpty()) {
+ return LogicConstantNode.contradiction();
+ } else if (exact && !succeedingXStamp.isEmpty()) {
+ int bits = succeedingXStamp.getBits();
+ if (compare(lowerBound(succeedingXStamp), minValue(bits)) > 0) {
+ assert upperBound(succeedingXStamp) == maxValue(bits);
+ // x must be in [L..MAX] <=> x >= L <=> !(x < L)
+ return LogicNegationNode.create(create(forX, ConstantNode.forIntegerStamp(succeedingXStamp, lowerBound(succeedingXStamp))));
+ } else if (compare(upperBound(succeedingXStamp), maxValue(bits)) < 0) {
+ // x must be in [MIN..H] <=> x <= H <=> !(H < x)
+ return LogicNegationNode.create(create(ConstantNode.forIntegerStamp(succeedingXStamp, upperBound(succeedingXStamp)), forX));
+ }
+ }
return null;
}
@@ -268,7 +293,7 @@
return null;
}
- protected IntegerStamp getSucceedingStampForXLowerXPlusA(boolean negated, boolean strict, IntegerStamp a) {
+ protected IntegerStamp getSucceedingStampForXLowerXPlusA(boolean mirrored, boolean strict, IntegerStamp a) {
int bits = a.getBits();
long min = minValue(bits);
long max = maxValue(bits);
@@ -286,7 +311,7 @@
* This does not use upper/lowerBound from LowerOp because it's about the (signed)
* addition not the comparison.
*/
- if (negated) {
+ if (mirrored) {
if (a.contains(0)) {
// a may be zero
return a.unrestricted();
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -57,8 +57,7 @@
}
public static LogicNode create(ValueNode forValue) {
- LogicNode result = tryCanonicalize(forValue);
- return result == null ? new IsNullNode(GraphUtil.skipPi(forValue)) : result;
+ return canonicalized(null, forValue);
}
public static LogicNode tryCanonicalize(ValueNode forValue) {
@@ -84,7 +83,11 @@
@Override
public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+ return canonicalized(this, forValue);
+ }
+ private static LogicNode canonicalized(IsNullNode isNullNode, ValueNode forValue) {
+ IsNullNode self = isNullNode;
LogicNode result = tryCanonicalize(forValue);
if (result != null) {
return result;
@@ -101,7 +104,10 @@
}
}
- return this;
+ if (self == null) {
+ self = new IsNullNode(GraphUtil.skipPi(forValue));
+ }
+ return self;
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/LeftShiftNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/LeftShiftNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -24,6 +24,8 @@
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp.Shl;
+import org.graalvm.compiler.core.common.type.IntegerStamp;
+import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool;
@@ -43,6 +45,17 @@
super(TYPE, ArithmeticOpTable::getShl, x, y);
}
+ public static ValueNode create(ValueNode x, ValueNode y) {
+ ArithmeticOpTable.ShiftOp<Shl> op = ArithmeticOpTable.forStamp(x.stamp()).getShl();
+ Stamp stamp = op.foldStamp(x.stamp(), (IntegerStamp) y.stamp());
+ ValueNode value = ShiftNode.canonical(op, stamp, x, y);
+ if (value != null) {
+ return value;
+ }
+
+ return canonical(null, op, stamp, x, y);
+ }
+
@Override
public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
ValueNode ret = super.canonical(tool, forX, forY);
@@ -50,10 +63,15 @@
return ret;
}
+ return canonical(this, getArithmeticOp(), stamp(), forX, forY);
+ }
+
+ private static ValueNode canonical(LeftShiftNode leftShiftNode, ArithmeticOpTable.ShiftOp<Shl> op, Stamp stamp, ValueNode forX, ValueNode forY) {
+ LeftShiftNode self = leftShiftNode;
if (forY.isConstant()) {
int amount = forY.asJavaConstant().asInt();
- int originalAmout = amount;
- int mask = getShiftAmountMask();
+ int originalAmount = amount;
+ int mask = op.getShiftAmountMask(stamp);
amount &= mask;
if (amount == 0) {
return forX;
@@ -65,24 +83,27 @@
if (other instanceof LeftShiftNode) {
int total = amount + otherAmount;
if (total != (total & mask)) {
- return ConstantNode.forIntegerKind(getStackKind(), 0);
+ return ConstantNode.forIntegerKind(stamp.getStackKind(), 0);
}
return new LeftShiftNode(other.getX(), ConstantNode.forInt(total));
} else if ((other instanceof RightShiftNode || other instanceof UnsignedRightShiftNode) && otherAmount == amount) {
- if (getStackKind() == JavaKind.Long) {
+ if (stamp.getStackKind() == JavaKind.Long) {
return new AndNode(other.getX(), ConstantNode.forLong(-1L << amount));
} else {
- assert getStackKind() == JavaKind.Int;
+ assert stamp.getStackKind() == JavaKind.Int;
return new AndNode(other.getX(), ConstantNode.forInt(-1 << amount));
}
}
}
}
- if (originalAmout != amount) {
+ if (originalAmount != amount) {
return new LeftShiftNode(forX, ConstantNode.forInt(amount));
}
}
- return this;
+ if (self == null) {
+ self = new LeftShiftNode(forX, forY);
+ }
+ return self;
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/MulNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/MulNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -60,9 +60,8 @@
ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp);
if (tryConstantFold != null) {
return tryConstantFold;
- } else {
- return new MulNode(x, y).maybeCommuteInputs();
}
+ return canonical(null, op, stamp, x, y);
}
@Override
@@ -81,8 +80,12 @@
// if this fails we only swap
return new MulNode(forY, forX);
}
+ BinaryOp<Mul> op = getOp(forX, forY);
+ return canonical(this, op, stamp(), forX, forY);
+ }
+
+ private static ValueNode canonical(MulNode self, BinaryOp<Mul> op, Stamp stamp, ValueNode forX, ValueNode forY) {
if (forY.isConstant()) {
- BinaryOp<Mul> op = getOp(forX, forY);
Constant c = forY.asConstant();
if (op.isNeutral(c)) {
return forX;
@@ -96,7 +99,7 @@
} else if (i == 1) {
return forX;
} else if (i == -1) {
- return new NegateNode(forX);
+ return NegateNode.create(forX);
} else if (i > 0) {
if (CodeUtil.isPowerOf2(i)) {
return new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(i)));
@@ -107,17 +110,17 @@
}
} else if (i < 0) {
if (CodeUtil.isPowerOf2(-i)) {
- return new NegateNode(new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(-i))));
+ return NegateNode.create(LeftShiftNode.create(forX, ConstantNode.forInt(CodeUtil.log2(-i))));
}
}
}
if (op.isAssociative()) {
// canonicalize expressions like "(a * 1) * 2"
- return reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
+ return reassociate(self != null ? self : (MulNode) new MulNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY);
}
}
- return this;
+ return self != null ? self : new MulNode(forX, forY).maybeCommuteInputs();
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NegateNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NegateNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -49,20 +49,37 @@
super(TYPE, ArithmeticOpTable::getNeg, value);
}
+ public static ValueNode create(ValueNode value) {
+ ValueNode synonym = findSynonym(value);
+ if (synonym != null) {
+ return synonym;
+ }
+ return new NegateNode(value);
+ }
+
@Override
public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
- ValueNode ret = super.canonical(tool, forValue);
- if (ret != this) {
- return ret;
+ ValueNode synonym = findSynonym(forValue, getOp(forValue));
+ if (synonym != null) {
+ return synonym;
+ }
+ return this;
+ }
+
+ protected static ValueNode findSynonym(ValueNode forValue) {
+ ArithmeticOpTable.UnaryOp<Neg> negOp = ArithmeticOpTable.forStamp(forValue.stamp()).getNeg();
+ ValueNode synonym = UnaryArithmeticNode.findSynonym(forValue, negOp);
+ if (synonym != null) {
+ return synonym;
}
if (forValue instanceof NegateNode) {
return ((NegateNode) forValue).getValue();
}
if (forValue instanceof SubNode && !(forValue.stamp() instanceof FloatStamp)) {
SubNode sub = (SubNode) forValue;
- return new SubNode(sub.getY(), sub.getX());
+ return SubNode.create(sub.getY(), sub.getX());
}
- return this;
+ return null;
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -93,11 +93,11 @@
LogicNode equalComp;
LogicNode lessComp;
if (getX().stamp() instanceof FloatStamp) {
- equalComp = graph().unique(FloatEqualsNode.create(getX(), getY(), tool.getConstantReflection()));
- lessComp = graph().unique(FloatLessThanNode.create(getX(), getY(), isUnorderedLess, tool.getConstantReflection()));
+ equalComp = graph().addOrUniqueWithInputs(FloatEqualsNode.create(getX(), getY()));
+ lessComp = graph().addOrUniqueWithInputs(FloatLessThanNode.create(getX(), getY(), isUnorderedLess));
} else {
- equalComp = graph().unique(IntegerEqualsNode.create(getX(), getY(), tool.getConstantReflection()));
- lessComp = graph().unique(IntegerLessThanNode.create(getX(), getY(), tool.getConstantReflection()));
+ equalComp = graph().addOrUniqueWithInputs(IntegerEqualsNode.create(getX(), getY()));
+ lessComp = graph().addOrUniqueWithInputs(IntegerLessThanNode.create(getX(), getY()));
}
ConditionalNode equalValue = graph().unique(new ConditionalNode(equalComp, ConstantNode.forInt(0, graph()), ConstantNode.forInt(1, graph())));
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/OrNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/OrNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -56,9 +56,8 @@
ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp);
if (tryConstantFold != null) {
return tryConstantFold;
- } else {
- return new OrNode(x, y).maybeCommuteInputs();
}
+ return canonical(null, op, stamp, x, y);
}
@Override
@@ -68,6 +67,10 @@
return ret;
}
+ return canonical(this, getOp(forX, forY), stamp(), forX, forY);
+ }
+
+ private static ValueNode canonical(OrNode self, BinaryOp<Or> op, Stamp stamp, ValueNode forX, ValueNode forY) {
if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
return forX;
}
@@ -76,20 +79,23 @@
}
if (forY.isConstant()) {
Constant c = forY.asConstant();
- if (getOp(forX, forY).isNeutral(c)) {
+ if (op.isNeutral(c)) {
return forX;
}
if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) {
long rawY = ((PrimitiveConstant) c).asLong();
- long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp()));
+ long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp));
if ((rawY & mask) == mask) {
- return ConstantNode.forIntegerStamp(stamp(), mask);
+ return ConstantNode.forIntegerStamp(stamp, mask);
}
}
- return reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
+ return reassociate(self != null ? self : (OrNode) new OrNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY);
}
- return this;
+ if (forX instanceof NotNode && forY instanceof NotNode) {
+ return new NotNode(AndNode.create(((NotNode) forX).getValue(), ((NotNode) forY).getValue()));
+ }
+ return self != null ? self : new OrNode(forX, forY).maybeCommuteInputs();
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RightShiftNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RightShiftNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -25,6 +25,7 @@
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp.Shr;
import org.graalvm.compiler.core.common.type.IntegerStamp;
+import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool;
@@ -44,6 +45,17 @@
super(TYPE, ArithmeticOpTable::getShr, x, y);
}
+ public static ValueNode create(ValueNode x, ValueNode y) {
+ ArithmeticOpTable.ShiftOp<Shr> op = ArithmeticOpTable.forStamp(x.stamp()).getShr();
+ Stamp stamp = op.foldStamp(x.stamp(), (IntegerStamp) y.stamp());
+ ValueNode value = ShiftNode.canonical(op, stamp, x, y);
+ if (value != null) {
+ return value;
+ }
+
+ return canonical(null, op, stamp, x, y);
+ }
+
@Override
public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
ValueNode ret = super.canonical(tool, forX, forY);
@@ -51,6 +63,11 @@
return ret;
}
+ return canonical(this, getArithmeticOp(), stamp(), forX, forY);
+ }
+
+ private static ValueNode canonical(RightShiftNode rightShiftNode, ArithmeticOpTable.ShiftOp<Shr> op, Stamp stamp, ValueNode forX, ValueNode forY) {
+ RightShiftNode self = rightShiftNode;
if (forX.stamp() instanceof IntegerStamp && ((IntegerStamp) forX.stamp()).isPositive()) {
return new UnsignedRightShiftNode(forX, forY);
}
@@ -58,7 +75,7 @@
if (forY.isConstant()) {
int amount = forY.asJavaConstant().asInt();
int originalAmout = amount;
- int mask = getShiftAmountMask();
+ int mask = op.getShiftAmountMask(stamp);
amount &= mask;
if (amount == 0) {
return forX;
@@ -74,10 +91,10 @@
IntegerStamp istamp = (IntegerStamp) other.getX().stamp();
if (istamp.isPositive()) {
- return ConstantNode.forIntegerKind(getStackKind(), 0);
+ return ConstantNode.forIntegerKind(stamp.getStackKind(), 0);
}
if (istamp.isStrictlyNegative()) {
- return ConstantNode.forIntegerKind(getStackKind(), -1L);
+ return ConstantNode.forIntegerKind(stamp.getStackKind(), -1L);
}
/*
@@ -95,7 +112,10 @@
return new RightShiftNode(forX, ConstantNode.forInt(amount));
}
}
- return this;
+ if (self == null) {
+ self = new RightShiftNode(forX, forY);
+ }
+ return self;
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ShiftNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ShiftNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -85,12 +85,20 @@
@Override
public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+ ValueNode valueNode = canonical(getOp(forX), stamp(), forX, forY);
+ if (valueNode != null) {
+ return valueNode;
+ }
+ return this;
+ }
+
+ public static <OP> ValueNode canonical(ShiftOp<OP> op, Stamp stamp, ValueNode forX, ValueNode forY) {
if (forX.isConstant() && forY.isConstant()) {
JavaConstant amount = forY.asJavaConstant();
assert amount.getJavaKind() == JavaKind.Int;
- return ConstantNode.forPrimitive(stamp(), getOp(forX).foldConstant(forX.asConstant(), amount.asInt()));
+ return ConstantNode.forPrimitive(stamp, op.foldConstant(forX.asConstant(), amount.asInt()));
}
- return this;
+ return null;
}
public int getShiftAmountMask() {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -63,9 +63,8 @@
ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp()));
if (synonym != null) {
return synonym;
- } else {
- return new SignExtendNode(input, inputBits, resultBits);
}
+ return canonical(null, input, inputBits, resultBits);
}
@Override
@@ -80,30 +79,34 @@
return ret;
}
+ return canonical(this, forValue, getInputBits(), getResultBits());
+ }
+
+ private static ValueNode canonical(SignExtendNode self, ValueNode forValue, int inputBits, int resultBits) {
if (forValue instanceof SignExtendNode) {
// sxxx -(sign-extend)-> ssss sxxx -(sign-extend)-> ssssssss sssssxxx
// ==> sxxx -(sign-extend)-> ssssssss sssssxxx
SignExtendNode other = (SignExtendNode) forValue;
- return SignExtendNode.create(other.getValue(), other.getInputBits(), getResultBits());
+ return SignExtendNode.create(other.getValue(), other.getInputBits(), resultBits);
} else if (forValue instanceof ZeroExtendNode) {
ZeroExtendNode other = (ZeroExtendNode) forValue;
if (other.getResultBits() > other.getInputBits()) {
// sxxx -(zero-extend)-> 0000 sxxx -(sign-extend)-> 00000000 0000sxxx
// ==> sxxx -(zero-extend)-> 00000000 0000sxxx
- return ZeroExtendNode.create(other.getValue(), other.getInputBits(), getResultBits());
+ return ZeroExtendNode.create(other.getValue(), other.getInputBits(), resultBits);
}
}
if (forValue.stamp() instanceof IntegerStamp) {
IntegerStamp inputStamp = (IntegerStamp) forValue.stamp();
- if ((inputStamp.upMask() & (1L << (getInputBits() - 1))) == 0L) {
+ if ((inputStamp.upMask() & (1L << (inputBits - 1))) == 0L) {
// 0xxx -(sign-extend)-> 0000 0xxx
// ==> 0xxx -(zero-extend)-> 0000 0xxx
- return ZeroExtendNode.create(forValue, getInputBits(), getResultBits());
+ return ZeroExtendNode.create(forValue, inputBits, resultBits);
}
}
- return this;
+ return self != null ? self : new SignExtendNode(forValue, inputBits, resultBits);
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -67,7 +67,7 @@
return forX;
}
if (c == -1) {
- return new NegateNode(forX);
+ return NegateNode.create(forX);
}
long abs = Math.abs(c);
if (CodeUtil.isPowerOf2(abs) && forX.stamp() instanceof IntegerStamp) {
@@ -83,7 +83,7 @@
}
RightShiftNode shift = new RightShiftNode(dividend, ConstantNode.forInt(log2));
if (c < 0) {
- return new NegateNode(shift);
+ return NegateNode.create(shift);
}
return shift;
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SubNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SubNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -59,24 +59,16 @@
ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp);
if (tryConstantFold != null) {
return tryConstantFold;
- } else {
- return new SubNode(x, y);
}
+ return canonical(null, op, stamp, x, y);
}
- @SuppressWarnings("hiding")
- @Override
- public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
- ValueNode ret = super.canonical(tool, forX, forY);
- if (ret != this) {
- return ret;
- }
-
- BinaryOp<Sub> op = getOp(forX, forY);
+ private static ValueNode canonical(SubNode subNode, BinaryOp<Sub> op, Stamp stamp, ValueNode forX, ValueNode forY) {
+ SubNode self = subNode;
if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
Constant zero = op.getZero(forX.stamp());
if (zero != null) {
- return ConstantNode.forPrimitive(stamp(), zero);
+ return ConstantNode.forPrimitive(stamp, zero);
}
}
boolean associative = op.isAssociative();
@@ -95,18 +87,18 @@
SubNode x = (SubNode) forX;
if (x.getX() == forY) {
// (a - b) - a
- return new NegateNode(x.getY());
+ return NegateNode.create(x.getY());
}
}
if (forY instanceof AddNode) {
AddNode y = (AddNode) forY;
if (y.getX() == forX) {
// a - (a + b)
- return new NegateNode(y.getY());
+ return NegateNode.create(y.getY());
}
if (y.getY() == forX) {
// b - (a + b)
- return new NegateNode(y.getX());
+ return NegateNode.create(y.getX());
}
} else if (forY instanceof SubNode) {
SubNode y = (SubNode) forY;
@@ -121,9 +113,9 @@
if (op.isNeutral(c)) {
return forX;
}
- if (associative) {
- ValueNode reassociated = reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
- if (reassociated != this) {
+ if (associative && self != null) {
+ ValueNode reassociated = reassociate(self, ValueNode.isConstantPredicate(), forX, forY);
+ if (reassociated != self) {
return reassociated;
}
}
@@ -132,27 +124,41 @@
if (i < 0 || ((IntegerStamp) StampFactory.forKind(forY.getStackKind())).contains(-i)) {
// Adding a negative is more friendly to the backend since adds are
// commutative, so prefer add when it fits.
- return BinaryArithmeticNode.add(forX, ConstantNode.forIntegerStamp(stamp(), -i));
+ return BinaryArithmeticNode.add(forX, ConstantNode.forIntegerStamp(stamp, -i));
}
}
} else if (forX.isConstant()) {
Constant c = forX.asConstant();
- if (ArithmeticOpTable.forStamp(stamp()).getAdd().isNeutral(c)) {
+ if (ArithmeticOpTable.forStamp(stamp).getAdd().isNeutral(c)) {
/*
* Note that for floating point numbers, + and - have different neutral elements. We
* have to test for the neutral element of +, because we are doing this
* transformation: 0 - x == (-x) + 0 == -x.
*/
- return new NegateNode(forY);
+ return NegateNode.create(forY);
}
- if (associative) {
- return reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
+ if (associative && self != null) {
+ return reassociate(self, ValueNode.isConstantPredicate(), forX, forY);
}
}
if (forY instanceof NegateNode) {
return BinaryArithmeticNode.add(forX, ((NegateNode) forY).getValue());
}
- return this;
+ if (self == null) {
+ self = new SubNode(forX, forY);
+ }
+ return self;
+ }
+
+ @Override
+ public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+ ValueNode ret = super.canonical(tool, forX, forY);
+ if (ret != this) {
+ return ret;
+ }
+
+ BinaryOp<Sub> op = getOp(forX, forY);
+ return canonical(this, op, stamp, forX, forY);
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/XorNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/XorNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -57,9 +57,8 @@
ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp);
if (tryConstantFold != null) {
return tryConstantFold;
- } else {
- return new XorNode(x, y).maybeCommuteInputs();
}
+ return canonical(null, op, stamp, x, y);
}
@Override
@@ -69,28 +68,32 @@
return ret;
}
+ return canonical(this, getOp(forX, forY), stamp(), forX, forY);
+ }
+
+ private static ValueNode canonical(XorNode self, BinaryOp<Xor> op, Stamp stamp, ValueNode forX, ValueNode forY) {
if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
- return ConstantNode.forPrimitive(stamp(), getOp(forX, forY).getZero(forX.stamp()));
+ return ConstantNode.forPrimitive(stamp, op.getZero(forX.stamp()));
}
if (forX.isConstant() && !forY.isConstant()) {
return new XorNode(forY, forX);
}
if (forY.isConstant()) {
Constant c = forY.asConstant();
- if (getOp(forX, forY).isNeutral(c)) {
+ if (op.isNeutral(c)) {
return forX;
}
if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) {
long rawY = ((PrimitiveConstant) c).asLong();
- long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp()));
+ long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp));
if ((rawY & mask) == mask) {
return new NotNode(forX);
}
}
- return reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
+ return reassociate(self != null ? self : (XorNode) new XorNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY);
}
- return this;
+ return self != null ? self : new XorNode(forX, forY).maybeCommuteInputs();
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -67,9 +67,8 @@
ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp()));
if (synonym != null) {
return synonym;
- } else {
- return new ZeroExtendNode(input, inputBits, resultBits);
}
+ return canonical(null, input, inputBits, resultBits);
}
@Override
@@ -97,11 +96,16 @@
return ret;
}
+ return canonical(this, forValue, getInputBits(), getResultBits());
+ }
+
+ private static ValueNode canonical(ZeroExtendNode zeroExtendNode, ValueNode forValue, int inputBits, int resultBits) {
+ ZeroExtendNode self = zeroExtendNode;
if (forValue instanceof ZeroExtendNode) {
// xxxx -(zero-extend)-> 0000 xxxx -(zero-extend)-> 00000000 0000xxxx
// ==> xxxx -(zero-extend)-> 00000000 0000xxxx
ZeroExtendNode other = (ZeroExtendNode) forValue;
- return new ZeroExtendNode(other.getValue(), other.getInputBits(), getResultBits());
+ return new ZeroExtendNode(other.getValue(), other.getInputBits(), resultBits);
}
if (forValue instanceof NarrowNode) {
NarrowNode narrow = (NarrowNode) forValue;
@@ -128,7 +132,10 @@
}
}
- return this;
+ if (self == null) {
+ self = new ZeroExtendNode(forValue, inputBits, resultBits);
+ }
+ return self;
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java Thu Apr 06 23:01:27 2017 +0000
@@ -607,7 +607,7 @@
if (sux.loop != loop) {
AbstractBeginNode begin = sux.getBeginNode();
if (!(begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == loopBegin)) {
- Debug.log(Debug.VERBOSE_LOG_LEVEL, "Unexpected loop exit with %s, including whole branch in the loop", sux);
+ Debug.log(Debug.VERBOSE_LEVEL, "Unexpected loop exit with %s, including whole branch in the loop", sux);
computeLoopBlocks(sux, loop, stack, false);
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -97,23 +97,22 @@
}
boolean usageFound = false;
for (IntegerEqualsNode node : this.usages().filter(IntegerEqualsNode.class)) {
- if (node.condition() == Condition.EQ) {
- ValueNode other = node.getX();
- if (node.getX() == this) {
- other = node.getY();
+ assert node.condition() == Condition.EQ;
+ ValueNode other = node.getX();
+ if (node.getX() == this) {
+ other = node.getY();
+ }
+ if (other.isConstant()) {
+ double probabilityToSet = probabilityValue;
+ if (other.asJavaConstant().asInt() == 0) {
+ probabilityToSet = 1.0 - probabilityToSet;
}
- if (other.isConstant()) {
- double probabilityToSet = probabilityValue;
- if (other.asJavaConstant().asInt() == 0) {
- probabilityToSet = 1.0 - probabilityToSet;
- }
- for (IfNode ifNodeUsages : node.usages().filter(IfNode.class)) {
- usageFound = true;
- ifNodeUsages.setTrueSuccessorProbability(probabilityToSet);
- }
- if (!usageFound) {
- usageFound = node.usages().filter(NodePredicates.isA(FixedGuardNode.class).or(ConditionalNode.class)).isNotEmpty();
- }
+ for (IfNode ifNodeUsages : node.usages().filter(IfNode.class)) {
+ usageFound = true;
+ ifNodeUsages.setTrueSuccessorProbability(probabilityToSet);
+ }
+ if (!usageFound) {
+ usageFound = node.usages().filter(NodePredicates.isA(FixedGuardNode.class).or(ConditionalNode.class)).isNotEmpty();
}
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/IntegerSwitchNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/IntegerSwitchNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -194,7 +194,7 @@
} else {
int newDefaultSuccessor = addNewSuccessor(defaultSuccessor(), newSuccessors);
double newDefaultProbability = keyProbabilities[keyProbabilities.length - 1];
- doReplace(tool, value(), newKeyDatas, newSuccessors, newDefaultSuccessor, newDefaultProbability);
+ doReplace(value(), newKeyDatas, newSuccessors, newDefaultSuccessor, newDefaultProbability);
return true;
}
}
@@ -294,7 +294,7 @@
* Build the low-level representation of the new switch keys and replace ourself with a new
* node.
*/
- doReplace(tool, newValue, newKeyDatas, newSuccessors, newDefaultSuccessor, newDefaultProbability);
+ doReplace(newValue, newKeyDatas, newSuccessors, newDefaultSuccessor, newDefaultProbability);
/* The array load is now unnecessary. */
assert loadIndexed.hasNoUsages();
@@ -312,7 +312,7 @@
return index;
}
- private void doReplace(SimplifierTool tool, ValueNode newValue, List<KeyData> newKeyDatas, ArrayList<AbstractBeginNode> newSuccessors, int newDefaultSuccessor, double newDefaultProbability) {
+ private void doReplace(ValueNode newValue, List<KeyData> newKeyDatas, ArrayList<AbstractBeginNode> newSuccessors, int newDefaultSuccessor, double newDefaultProbability) {
/* Sort the new keys (invariant of the IntegerSwitchNode). */
newKeyDatas.sort((k1, k2) -> k1.key - k2.key);
@@ -353,7 +353,7 @@
if (!newSuccessors.contains(successor)) {
FixedNode fixedBranch = successor;
fixedBranch.predecessor().replaceFirstSuccessor(fixedBranch, null);
- GraphUtil.killCFG(fixedBranch, tool);
+ GraphUtil.killCFG(fixedBranch);
}
setBlockSuccessor(i, null);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -27,6 +27,7 @@
import org.graalvm.compiler.core.common.LocationIdentity;
import org.graalvm.compiler.core.common.type.PrimitiveStamp;
+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;
@@ -52,10 +53,21 @@
public class RawLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable {
public static final NodeClass<RawLoadNode> TYPE = NodeClass.create(RawLoadNode.class);
+ /**
+ * This constructor exists for node intrinsics that need a stamp based on {@code accessKind}.
+ */
public RawLoadNode(ValueNode object, ValueNode offset, JavaKind accessKind, LocationIdentity locationIdentity) {
super(TYPE, StampFactory.forKind(accessKind.getStackKind()), object, offset, accessKind, locationIdentity, false);
}
+ /**
+ * This constructor exists for node intrinsics that need a stamp based on the return type of the
+ * {@link org.graalvm.compiler.graph.Node.NodeIntrinsic} annotated method.
+ */
+ public RawLoadNode(@InjectedNodeParameter Stamp stamp, ValueNode object, ValueNode offset, LocationIdentity locationIdentity, JavaKind accessKind) {
+ super(TYPE, stamp, object, offset, accessKind, locationIdentity, false);
+ }
+
public RawLoadNode(NodeClass<? extends RawLoadNode> c, ValueNode object, ValueNode offset, JavaKind accessKind, LocationIdentity locationIdentity) {
super(c, StampFactory.forKind(accessKind.getStackKind()), object, offset, accessKind, locationIdentity, false);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeCopyNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeCopyNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -22,15 +22,15 @@
*/
package org.graalvm.compiler.nodes.extended;
-import jdk.vm.ci.meta.JavaKind;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
import org.graalvm.compiler.core.common.LocationIdentity;
import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
/**
* Copy a value at a location specified as an offset relative to a source object to another location
* specified as an offset relative to destination object. No null checks are performed.
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java Thu Apr 06 23:01:27 2017 +0000
@@ -70,8 +70,9 @@
void push(JavaKind kind, ValueNode value);
/**
- * Adds a node to the graph. If the returned node is a {@link StateSplit} with a null
- * {@linkplain StateSplit#stateAfter() frame state}, the frame state is initialized.
+ * Adds a node to the graph. If the node is in the graph, returns immediately. If the node is a
+ * {@link StateSplit} with a null {@linkplain StateSplit#stateAfter() frame state}, the frame
+ * state is initialized.
*
* @param value the value to add to the graph and push to the stack. The
* {@code value.getJavaKind()} kind is used when type checking this operation.
@@ -92,6 +93,30 @@
return equivalentValue;
}
+ /**
+ * Adds a node and its inputs to the graph. If the node is in the graph, returns immediately. If
+ * the node is a {@link StateSplit} with a null {@linkplain StateSplit#stateAfter() frame state}
+ * , the frame state is initialized.
+ *
+ * @param value the value to add to the graph and push to the stack. The
+ * {@code value.getJavaKind()} kind is used when type checking this operation.
+ * @return a node equivalent to {@code value} in the graph
+ */
+ default <T extends ValueNode> T addWithInputs(T value) {
+ if (value.graph() != null) {
+ assert !(value instanceof StateSplit) || ((StateSplit) value).stateAfter() != null;
+ return value;
+ }
+ T equivalentValue = recursiveAppend(value);
+ if (equivalentValue instanceof StateSplit) {
+ StateSplit stateSplit = (StateSplit) equivalentValue;
+ if (stateSplit.stateAfter() == null && stateSplit.hasSideEffect()) {
+ setStateAfter(stateSplit);
+ }
+ }
+ return equivalentValue;
+ }
+
default ValueNode addNonNullCast(ValueNode value) {
AbstractPointerStamp valueStamp = (AbstractPointerStamp) value.stamp();
if (valueStamp.nonNull()) {
@@ -100,7 +125,7 @@
LogicNode isNull = add(IsNullNode.create(value));
FixedGuardNode fixedGuard = add(new FixedGuardNode(isNull, DeoptimizationReason.NullCheckException, DeoptimizationAction.None, true));
Stamp newStamp = valueStamp.improveWith(StampFactory.objectNonNull());
- return add(new PiNode(value, newStamp, fixedGuard));
+ return add(PiNode.create(value, newStamp, fixedGuard));
}
}
@@ -245,12 +270,12 @@
* non-null} stamp.
*/
default ValueNode nullCheckedValue(ValueNode value, DeoptimizationAction action) {
- if (!StampTool.isPointerNonNull(value.stamp())) {
+ if (!StampTool.isPointerNonNull(value)) {
LogicNode condition = getGraph().unique(IsNullNode.create(value));
ObjectStamp receiverStamp = (ObjectStamp) value.stamp();
Stamp stamp = receiverStamp.join(objectNonNull());
FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, NullCheckException, action, true));
- PiNode nonNullReceiver = getGraph().unique(new PiNode(value, stamp, fixedGuard));
+ ValueNode nonNullReceiver = getGraph().addOrUnique(PiNode.create(value, stamp, fixedGuard));
// TODO: Propogating the non-null into the frame state would
// remove subsequent null-checks on the same value. However,
// it currently causes an assertion failure when merging states.
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodeIntrinsicPluginFactory.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodeIntrinsicPluginFactory.java Thu Apr 06 23:01:27 2017 +0000
@@ -30,7 +30,14 @@
<T> T getInjectedArgument(Class<T> type);
- Stamp getReturnStamp(Class<?> type, boolean nonNull);
+ /**
+ * Gets a stamp denoting a given type and non-nullness property.
+ *
+ * @param type the type the returned stamp represents
+ * @param nonNull specifies if the returned stamp denotes a value that is guaranteed to be
+ * non-null
+ */
+ Stamp getInjectedStamp(Class<?> type, boolean nonNull);
}
void registerPlugins(InvocationPlugins plugins, InjectionProvider injection);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadFieldNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadFieldNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -24,6 +24,8 @@
import static org.graalvm.compiler.graph.iterators.NodePredicates.isNotA;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.StampPair;
@@ -51,6 +53,7 @@
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
+import org.graalvm.compiler.options.OptionValues;
/**
* The {@code LoadFieldNode} represents a read of a static or instance field.
@@ -71,10 +74,21 @@
return new LoadFieldNode(StampFactory.forDeclaredType(assumptions, field.getType(), false), object, field);
}
+ public static ValueNode create(ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess,
+ OptionValues options, Assumptions assumptions, ValueNode object, ResolvedJavaField field, boolean canonicalizeReads, boolean allUsagesAvailable) {
+ return canonical(null, StampFactory.forDeclaredType(assumptions, field.getType(), false), object,
+ field, constantFields, constantReflection, options, metaAccess, canonicalizeReads, allUsagesAvailable);
+ }
+
public static LoadFieldNode createOverrideStamp(StampPair stamp, ValueNode object, ResolvedJavaField field) {
return new LoadFieldNode(stamp, object, field);
}
+ public static ValueNode createOverrideStamp(ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess,
+ OptionValues options, StampPair stamp, ValueNode object, ResolvedJavaField field, boolean canonicalizeReads, boolean allUsagesAvailable) {
+ return canonical(null, stamp, object, field, constantFields, constantReflection, options, metaAccess, canonicalizeReads, allUsagesAvailable);
+ }
+
@Override
public ValueNode getValue() {
return object();
@@ -85,33 +99,50 @@
if (tool.allUsagesAvailable() && hasNoUsages() && !isVolatile() && (isStatic() || StampTool.isPointerNonNull(forObject.stamp()))) {
return null;
}
- MetaAccessProvider metaAccess = tool.getMetaAccess();
- if (tool.canonicalizeReads() && metaAccess != null) {
- ConstantNode constant = asConstant(tool, forObject);
+ return canonical(this, StampPair.create(stamp, uncheckedStamp), forObject, field, tool.getConstantFieldProvider(),
+ tool.getConstantReflection(), tool.getOptions(), tool.getMetaAccess(), tool.canonicalizeReads(), tool.allUsagesAvailable());
+ }
+
+ private static ValueNode canonical(LoadFieldNode loadFieldNode, StampPair stamp, ValueNode forObject, ResolvedJavaField field,
+ ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection,
+ OptionValues options, MetaAccessProvider metaAccess, boolean canonicalizeReads, boolean allUsagesAvailable) {
+ LoadFieldNode self = loadFieldNode;
+ if (canonicalizeReads && metaAccess != null) {
+ ConstantNode constant = asConstant(constantFields, constantReflection, metaAccess, options, forObject, field);
if (constant != null) {
return constant;
}
- if (tool.allUsagesAvailable()) {
- PhiNode phi = asPhi(tool, forObject);
+ if (allUsagesAvailable) {
+ PhiNode phi = asPhi(constantFields, constantReflection, metaAccess, options, forObject,
+ field, stamp.getTrustedStamp());
if (phi != null) {
return phi;
}
}
}
- if (!isStatic() && forObject.isNullConstant()) {
+ if (self != null && !field.isStatic() && forObject.isNullConstant()) {
return new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException);
}
- return this;
+ if (self == null) {
+ self = new LoadFieldNode(stamp, forObject, field);
+ }
+ return self;
}
/**
* Gets a constant value for this load if possible.
*/
public ConstantNode asConstant(CanonicalizerTool tool, ValueNode forObject) {
- if (isStatic()) {
- return ConstantFoldUtil.tryConstantFold(tool.getConstantFieldProvider(), tool.getConstantReflection(), tool.getMetaAccess(), field(), null, getOptions());
+ return asConstant(tool.getConstantFieldProvider(), tool.getConstantReflection(),
+ tool.getMetaAccess(), tool.getOptions(), forObject, field);
+ }
+
+ private static ConstantNode asConstant(ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection,
+ MetaAccessProvider metaAccess, OptionValues options, ValueNode forObject, ResolvedJavaField field) {
+ if (field.isStatic()) {
+ return ConstantFoldUtil.tryConstantFold(constantFields, constantReflection, metaAccess, field, null, options);
} else if (forObject.isConstant() && !forObject.isNullConstant()) {
- return ConstantFoldUtil.tryConstantFold(tool.getConstantFieldProvider(), tool.getConstantReflection(), tool.getMetaAccess(), field(), forObject.asJavaConstant(), getOptions());
+ return ConstantFoldUtil.tryConstantFold(constantFields, constantReflection, metaAccess, field, forObject.asJavaConstant(), options);
}
return null;
}
@@ -120,19 +151,20 @@
return ConstantFoldUtil.tryConstantFold(tool.getConstantFieldProvider(), tool.getConstantReflection(), tool.getMetaAccess(), field(), constant, getOptions());
}
- private PhiNode asPhi(CanonicalizerTool tool, ValueNode forObject) {
- if (!isStatic() && field.isFinal() && forObject instanceof ValuePhiNode && ((ValuePhiNode) forObject).values().filter(isNotA(ConstantNode.class)).isEmpty()) {
+ private static PhiNode asPhi(ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection,
+ MetaAccessProvider metaAcccess, OptionValues options, ValueNode forObject, ResolvedJavaField field, Stamp stamp) {
+ if (!field.isStatic() && field.isFinal() && forObject instanceof ValuePhiNode && ((ValuePhiNode) forObject).values().filter(isNotA(ConstantNode.class)).isEmpty()) {
PhiNode phi = (PhiNode) forObject;
ConstantNode[] constantNodes = new ConstantNode[phi.valueCount()];
for (int i = 0; i < phi.valueCount(); i++) {
- ConstantNode constant = ConstantFoldUtil.tryConstantFold(tool.getConstantFieldProvider(), tool.getConstantReflection(), tool.getMetaAccess(), field(), phi.valueAt(i).asJavaConstant(),
- getOptions());
+ ConstantNode constant = ConstantFoldUtil.tryConstantFold(constantFields, constantReflection, metaAcccess, field, phi.valueAt(i).asJavaConstant(),
+ options);
if (constant == null) {
return null;
}
constantNodes[i] = constant;
}
- return new ValuePhiNode(stamp(), phi.merge(), constantNodes);
+ return new ValuePhiNode(stamp, phi.merge(), constantNodes);
}
return null;
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -239,8 +239,8 @@
LogicNode condition = graph().addOrUniqueWithInputs(InstanceOfNode.create(speculatedType, receiver, getProfile(), anchor));
FixedGuardNode guard = graph().add(new FixedGuardNode(condition, DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, false));
graph().addBeforeFixed(invoke().asNode(), guard);
- PiNode piNode = graph().unique(new PiNode(receiver, StampFactory.objectNonNull(speculatedType), guard));
- arguments().set(0, piNode);
+ ValueNode valueNode = graph().addOrUnique(new PiNode(receiver, StampFactory.objectNonNull(speculatedType), guard));
+ arguments().set(0, valueNode);
if (speculatedType.isExact()) {
setInvokeKind(InvokeKind.Special);
} else {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorIdNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorIdNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -45,6 +45,7 @@
public static final NodeClass<MonitorIdNode> TYPE = NodeClass.create(MonitorIdNode.class);
protected int lockDepth;
+ protected boolean eliminated;
public MonitorIdNode(int lockDepth) {
this(TYPE, lockDepth);
@@ -63,6 +64,14 @@
this.lockDepth = lockDepth;
}
+ public boolean isEliminated() {
+ return eliminated;
+ }
+
+ public void setEliminated() {
+ eliminated = true;
+ }
+
@Override
public void generate(NodeLIRBuilderTool generator) {
// nothing to do
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/NodeValueMap.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/NodeValueMap.java Thu Apr 06 23:01:27 2017 +0000
@@ -53,7 +53,7 @@
Value setResult(ValueNode node, Value operand);
/**
- * Gets the the {@link ValueNode} that produced a {@code value}. If the {@code value} is not
+ * Gets the {@link ValueNode} that produced a {@code value}. If the {@code value} is not
* associated with a {@link ValueNode} {@code null} is returned.
*
* This method is intended for debugging purposes only.
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/type/StampTool.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/type/StampTool.java Thu Apr 06 23:01:27 2017 +0000
@@ -78,7 +78,7 @@
public static Stamp unsignedCompare(Stamp stamp, Stamp stamp2) {
IntegerStamp x = (IntegerStamp) stamp;
IntegerStamp y = (IntegerStamp) stamp2;
- if (x == x.unrestricted() && y == y.unrestricted()) {
+ if (x.isUnrestricted() && y.isUnrestricted()) {
// Don't know anything.
return null;
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Thu Apr 06 23:01:27 2017 +0000
@@ -32,21 +32,19 @@
import org.graalvm.compiler.code.SourceStackTraceBailoutException;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
import org.graalvm.compiler.core.common.type.ObjectStamp;
-import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.debug.Debug;
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node;
-import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeSourcePosition;
+import org.graalvm.compiler.graph.NodeStack;
import org.graalvm.compiler.graph.NodeWorkList;
import org.graalvm.compiler.graph.Position;
import org.graalvm.compiler.graph.iterators.NodeIterable;
import org.graalvm.compiler.graph.spi.SimplifierTool;
-import org.graalvm.compiler.nodeinfo.InputType;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractEndNode;
import org.graalvm.compiler.nodes.AbstractMergeNode;
+import org.graalvm.compiler.nodes.ControlSplitNode;
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.FixedWithNextNode;
import org.graalvm.compiler.nodes.FrameState;
@@ -60,7 +58,6 @@
import org.graalvm.compiler.nodes.StateSplit;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.spi.ArrayLengthProvider;
import org.graalvm.compiler.nodes.spi.LimitedValueProxy;
@@ -70,8 +67,10 @@
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.util.EconomicMap;
import org.graalvm.util.EconomicSet;
import org.graalvm.util.Equivalence;
+import org.graalvm.util.MapCursor;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.code.BytecodePosition;
@@ -88,14 +87,142 @@
public static final OptionKey<Boolean> VerifyKillCFGUnusedNodes = new OptionKey<>(false);
}
+ private static void killCFGInner(FixedNode node) {
+ EconomicSet<Node> markedNodes = EconomicSet.create();
+ EconomicMap<AbstractMergeNode, List<AbstractEndNode>> unmarkedMerges = EconomicMap.create();
+
+ // Detach this node from CFG
+ node.replaceAtPredecessor(null);
+
+ markFixedNodes(node, markedNodes, unmarkedMerges);
+
+ fixSurvivingAffectedMerges(markedNodes, unmarkedMerges);
+
+ Debug.dump(Debug.DETAILED_LEVEL, node.graph(), "After fixing merges (killCFG %s)", node);
+
+ // Mark non-fixed nodes
+ markUsages(markedNodes);
+
+ // Detach marked nodes from non-marked nodes
+ for (Node marked : markedNodes) {
+ for (Node input : marked.inputs()) {
+ if (!markedNodes.contains(input)) {
+ marked.replaceFirstInput(input, null);
+ tryKillUnused(input);
+ }
+ }
+ }
+ Debug.dump(Debug.VERY_DETAILED_LEVEL, node.graph(), "After disconnecting non-marked inputs (killCFG %s)", node);
+ // Kill marked nodes
+ for (Node marked : markedNodes) {
+ if (marked.isAlive()) {
+ marked.markDeleted();
+ }
+ }
+ }
+
+ private static void markFixedNodes(FixedNode node, EconomicSet<Node> markedNodes, EconomicMap<AbstractMergeNode, List<AbstractEndNode>> unmarkedMerges) {
+ NodeStack workStack = new NodeStack();
+ workStack.push(node);
+ while (!workStack.isEmpty()) {
+ Node fixedNode = workStack.pop();
+ markedNodes.add(fixedNode);
+ if (fixedNode instanceof AbstractMergeNode) {
+ unmarkedMerges.removeKey((AbstractMergeNode) fixedNode);
+ }
+ while (fixedNode instanceof FixedWithNextNode) {
+ fixedNode = ((FixedWithNextNode) fixedNode).next();
+ if (fixedNode != null) {
+ markedNodes.add(fixedNode);
+ }
+ }
+ if (fixedNode instanceof ControlSplitNode) {
+ for (Node successor : fixedNode.successors()) {
+ workStack.push(successor);
+ }
+ } else if (fixedNode instanceof AbstractEndNode) {
+ AbstractEndNode end = (AbstractEndNode) fixedNode;
+ AbstractMergeNode merge = end.merge();
+ if (merge != null) {
+ assert !markedNodes.contains(merge) || (merge instanceof LoopBeginNode && end instanceof LoopEndNode) : merge;
+ if (merge instanceof LoopBeginNode) {
+ if (end == ((LoopBeginNode) merge).forwardEnd()) {
+ workStack.push(merge);
+ continue;
+ }
+ if (markedNodes.contains(merge)) {
+ continue;
+ }
+ }
+ List<AbstractEndNode> endsSeen = unmarkedMerges.get(merge);
+ if (endsSeen == null) {
+ endsSeen = new ArrayList<>(merge.forwardEndCount());
+ unmarkedMerges.put(merge, endsSeen);
+ }
+ endsSeen.add(end);
+ if (!(end instanceof LoopEndNode) && endsSeen.size() == merge.forwardEndCount()) {
+ assert merge.forwardEnds().filter(n -> !markedNodes.contains(n)).isEmpty();
+ // all this merge's forward ends are marked: it needs to be killed
+ workStack.push(merge);
+ }
+ }
+ }
+ }
+ }
+
+ private static void fixSurvivingAffectedMerges(EconomicSet<Node> markedNodes, EconomicMap<AbstractMergeNode, List<AbstractEndNode>> unmarkedMerges) {
+ MapCursor<AbstractMergeNode, List<AbstractEndNode>> cursor = unmarkedMerges.getEntries();
+ while (cursor.advance()) {
+ AbstractMergeNode merge = cursor.getKey();
+ for (AbstractEndNode end : cursor.getValue()) {
+ merge.removeEnd(end);
+ }
+ if (merge.phiPredecessorCount() == 1) {
+ if (merge instanceof LoopBeginNode) {
+ LoopBeginNode loopBegin = (LoopBeginNode) merge;
+ assert merge.forwardEndCount() == 1;
+ for (LoopExitNode loopExit : loopBegin.loopExits().snapshot()) {
+ if (markedNodes.contains(loopExit)) {
+ /*
+ * disconnect from loop begin so that reduceDegenerateLoopBegin doesn't
+ * transform it into a new beginNode
+ */
+ loopExit.replaceFirstInput(loopBegin, null);
+ }
+ }
+ merge.graph().reduceDegenerateLoopBegin(loopBegin);
+ } else {
+ merge.graph().reduceTrivialMerge(merge);
+ }
+ } else {
+ assert merge.phiPredecessorCount() > 1 : merge;
+ }
+ }
+ }
+
+ private static void markUsages(EconomicSet<Node> markedNodes) {
+ NodeStack workStack = new NodeStack(markedNodes.size() + 4);
+ for (Node marked : markedNodes) {
+ workStack.push(marked);
+ }
+ while (!workStack.isEmpty()) {
+ Node marked = workStack.pop();
+ for (Node usage : marked.usages()) {
+ if (!markedNodes.contains(usage)) {
+ workStack.push(usage);
+ markedNodes.add(usage);
+ }
+ }
+ }
+ }
+
@SuppressWarnings("try")
- public static void killCFG(FixedNode node, SimplifierTool tool) {
+ public static void killCFG(FixedNode node) {
try (Debug.Scope scope = Debug.scope("KillCFG", node)) {
EconomicSet<Node> unusedNodes = null;
EconomicSet<Node> unsafeNodes = null;
Graph.NodeEventScope nodeEventScope = null;
OptionValues options = node.getOptions();
- StructuredGraph graph = node.graph();
if (Graph.Options.VerifyGraalGraphEdges.getValue(options)) {
unsafeNodes = collectUnsafeNodes(node.graph());
}
@@ -110,14 +237,9 @@
}
});
}
- Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, node.graph(), "Before killCFG %s", node);
- NodeWorkList worklist = killCFG(node, tool, null);
- if (worklist != null) {
- for (Node n : worklist) {
- NodeWorkList list = killCFG(n, tool, worklist);
- assert list == worklist;
- }
- }
+ Debug.dump(Debug.VERY_DETAILED_LEVEL, node.graph(), "Before killCFG %s", node);
+ killCFGInner(node);
+ Debug.dump(Debug.VERY_DETAILED_LEVEL, node.graph(), "After killCFG %s", node);
if (Graph.Options.VerifyGraalGraphEdges.getValue(options)) {
EconomicSet<Node> newUnsafeNodes = collectUnsafeNodes(node.graph());
newUnsafeNodes.removeAll(unsafeNodes);
@@ -133,7 +255,6 @@
}
}
assert unusedNodes.isEmpty() : "New unused nodes: " + unusedNodes;
- assert graph.getNodes().filter(PoisonNode.class).isEmpty();
}
} catch (Throwable t) {
throw Debug.handle(t);
@@ -158,253 +279,10 @@
return unsafeNodes;
}
- private static NodeWorkList killCFG(Node node, SimplifierTool tool, NodeWorkList worklist) {
- NodeWorkList newWorklist = worklist;
- if (node instanceof FixedNode) {
- newWorklist = killCFGLinear((FixedNode) node, newWorklist, tool);
- } else {
- if (node instanceof PoisonNode && ((PoisonNode) node).processNonPhiUsagesFirst()) {
- if (node.isAlive()) {
- if (node.hasNoUsages()) {
- node.safeDelete();
- } else {
- if (newWorklist == null) {
- newWorklist = node.graph().createIterativeNodeWorkList(false, 0);
- }
- for (Node usage : node.usages()) {
- if (isFloatingNode(usage) && !(usage instanceof PhiNode)) {
- newWorklist.add(usage);
- }
- }
- newWorklist.add(node);
- }
- }
- } else {
- newWorklist = propagateKill(node, newWorklist);
- Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, node.graph(), "killCFG (Floating) %s", node);
- }
- }
- return newWorklist;
- }
-
- private static NodeWorkList killCFGLinear(FixedNode in, NodeWorkList worklist, SimplifierTool tool) {
- NodeWorkList newWorklist = worklist;
- FixedNode current = in;
- while (current != null) {
- FixedNode next = null;
- assert current.isAlive();
- if (current instanceof AbstractEndNode) {
- // We reached a control flow end.
- AbstractEndNode end = (AbstractEndNode) current;
- newWorklist = killEnd(end, newWorklist, tool);
- } else if (current instanceof FixedWithNextNode) {
- // Node guaranteed to have a single successor
- FixedWithNextNode fixedWithNext = (FixedWithNextNode) current;
- assert fixedWithNext.successors().count() == 1 || fixedWithNext.successors().count() == 0;
- assert fixedWithNext.successors().first() == fixedWithNext.next();
- next = fixedWithNext.next();
- } else {
- /*
- * We do not take a successor snapshot because this iterator supports concurrent
- * modifications as long as they do not change the size of the successor list. Not
- * taking a snapshot allows us to see modifications to other branches that may
- * happen while processing one branch.
- */
- Iterator<Node> successors = current.successors().iterator();
- if (successors.hasNext()) {
- Node first = successors.next();
- if (!successors.hasNext()) {
- next = (FixedNode) first;
- } else {
- if (newWorklist == null) {
- newWorklist = in.graph().createIterativeNodeWorkList(false, 0);
- }
- for (Node successor : current.successors()) {
- newWorklist.add(successor);
- if (successor instanceof LoopExitNode) {
- LoopExitNode exit = (LoopExitNode) successor;
- exit.replaceFirstInput(exit.loopBegin(), null);
- }
- }
- }
- }
- }
- current.replaceAtPredecessor(null);
- newWorklist = propagateKill(current, newWorklist);
- Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, current.graph(), "killCFGLinear %s", current);
- current = next;
- }
- Debug.dump(Debug.DETAILED_LOG_LEVEL, in.graph(), "killCFGLinear %s", in);
- return newWorklist;
- }
-
- public static void killCFG(FixedNode node) {
- killCFG(node, null);
- }
-
- /**
- * Node type used temporarily while deleting loops.
- *
- * It is used as replacement for the loop {@link PhiNode PhiNodes} in order to break data-flow
- * cycles before deleting the loop. The control-flow of the whole loop is killed before killing
- * the poison node if they are still alive.
- */
- @NodeInfo(allowedUsageTypes = InputType.Unchecked)
- private static final class PoisonNode extends FloatingNode {
- public static final NodeClass<PoisonNode> TYPE = NodeClass.create(PoisonNode.class);
- protected boolean loopPoison;
-
- protected PoisonNode(boolean loopPoison) {
- super(TYPE, StampFactory.forVoid());
- this.loopPoison = loopPoison;
- }
-
- public boolean processNonPhiUsagesFirst() {
- return !this.loopPoison;
- }
- }
-
- private static NodeWorkList killEnd(AbstractEndNode end, NodeWorkList worklist, SimplifierTool tool) {
- NodeWorkList newWorklist = worklist;
- AbstractMergeNode merge = end.merge();
- if (merge != null) {
- merge.removeEnd(end);
- StructuredGraph graph = end.graph();
- if (merge instanceof LoopBeginNode && merge.forwardEndCount() == 0) {
- // dead loop
- LoopBeginNode begin = (LoopBeginNode) merge;
- // disconnect and delete loop ends & loop exits
- for (LoopEndNode loopend : begin.loopEnds().snapshot()) {
- loopend.predecessor().replaceFirstSuccessor(loopend, null);
- loopend.safeDelete();
- }
- // clean unused proxies to avoid creating new unused nodes
- for (LoopExitNode exit : begin.loopExits()) {
- for (ProxyNode vpn : exit.proxies().snapshot()) {
- tryKillUnused(vpn);
- }
- }
- begin.removeExits();
- PoisonNode poison = null;
- if (merge.phis().isNotEmpty()) {
- poison = graph.addWithoutUnique(new PoisonNode(true));
- for (PhiNode phi : merge.phis()) {
- phi.replaceAtUsages(poison);
- }
- for (PhiNode phi : merge.phis().snapshot()) {
- killWithUnusedFloatingInputs(phi);
- }
- }
- FixedNode loopBody = begin.next();
- Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, end.graph(), "killEnd (Loop) %s after initial loop cleanup", end);
- if (loopBody != null) {
- // for small infinite loops, the body may already be killed while killing the
- // LoopEnds
- newWorklist = killCFG(loopBody, tool, newWorklist);
- }
- FrameState frameState = begin.stateAfter();
- begin.safeDelete();
- if (frameState != null) {
- tryKillUnused(frameState);
- }
- if (poison != null && poison.isAlive()) {
- if (newWorklist == null) {
- newWorklist = graph.createIterativeNodeWorkList(false, 0);
- }
- // drain the worklist to finish the loop before adding the poison
- List<Node> waitingPoisons = null;
- for (Node n : newWorklist) {
- if (n instanceof PoisonNode && ((PoisonNode) n).processNonPhiUsagesFirst() && n.hasUsages()) {
- assert n != poison;
- if (waitingPoisons == null) {
- waitingPoisons = new ArrayList<>(2);
- }
- waitingPoisons.add(n);
- } else {
- NodeWorkList list = killCFG(n, tool, newWorklist);
- assert list == newWorklist;
- }
- }
- if (poison.isAlive()) {
- newWorklist.add(poison);
- }
- if (waitingPoisons != null) {
- newWorklist.addAll(waitingPoisons);
- }
- }
- } else if (merge instanceof LoopBeginNode && ((LoopBeginNode) merge).loopEnds().isEmpty()) {
- // not a loop anymore
- if (tool != null) {
- for (PhiNode phi : merge.phis()) {
- tool.addToWorkList(phi.usages());
- }
- }
- graph.reduceDegenerateLoopBegin((LoopBeginNode) merge);
- } else if (merge.phiPredecessorCount() == 1) {
- // not a merge anymore
- for (PhiNode phi : merge.phis()) {
- if (tool != null) {
- tool.addToWorkList(phi.usages());
- }
- ValueNode value = phi.valueAt(0);
- if (value instanceof PoisonNode) {
- if (newWorklist == null) {
- newWorklist = graph.createIterativeNodeWorkList(false, 0);
- }
- newWorklist.add(value);
- }
- }
- graph.reduceTrivialMerge(merge);
- }
- }
- return newWorklist;
- }
-
public static boolean isFloatingNode(Node n) {
return !(n instanceof FixedNode);
}
- private static NodeWorkList propagateKill(Node node, NodeWorkList workList) {
- NodeWorkList newWorkList = workList;
- if (node != null && node.isAlive()) {
- if (node.hasUsages()) {
- for (Node usage : node.usages().snapshot()) {
- assert usage.isAlive();
- if (isFloatingNode(usage)) {
- boolean addUsage = false;
- if (usage instanceof PhiNode) {
- PhiNode phi = (PhiNode) usage;
- assert phi.merge() != null;
- if (phi.merge() == node) {
- // we reach the phi directly through he merge, queue it.
- addUsage = true;
- } else {
- // we reach it though a value
- assert phi.values().contains(node);
- // let that be handled when we reach the corresponding End node
- }
- } else {
- addUsage = true;
- }
- if (addUsage) {
- if (newWorkList == null) {
- newWorkList = node.graph().createIterativeNodeWorkList(false, 0);
- }
- newWorkList.add(usage);
- } else {
- usage.replaceFirstInput(node, node.graph().unique(new PoisonNode(false)));
- continue;
- }
- }
- usage.replaceFirstInput(node, null);
- }
- }
- assert node.hasNoUsages() : node + " " + node.usages().snapshot();
- killWithUnusedFloatingInputs(node, true);
- }
- return newWorkList;
- }
-
private static boolean checkKill(Node node, boolean mayKillGuard) {
node.assertTrue(mayKillGuard || !(node instanceof GuardNode), "must not be a guard node %s", node);
node.assertTrue(node.isAlive(), "must be alive");
@@ -972,7 +850,7 @@
public void deleteBranch(Node branch) {
FixedNode fixedBranch = (FixedNode) branch;
fixedBranch.predecessor().replaceFirstSuccessor(fixedBranch, null);
- GraphUtil.killCFG(fixedBranch, this);
+ GraphUtil.killCFG(fixedBranch);
}
@Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModifiableOptionValues.java Thu Apr 06 23:01:27 2017 +0000
@@ -0,0 +1,102 @@
+/*
+ * 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.options;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.graalvm.util.EconomicMap;
+import org.graalvm.util.Equivalence;
+import org.graalvm.util.UnmodifiableEconomicMap;
+import org.graalvm.util.UnmodifiableMapCursor;
+
+/**
+ * A context for obtaining values for {@link OptionKey}s that allows for key/value pairs to be
+ * updated. Updates have atomic copy-on-write semantics which means a thread may see an old value
+ * when reading but writers will never loose updates.
+ */
+public class ModifiableOptionValues extends OptionValues {
+
+ private final AtomicReference<UnmodifiableEconomicMap<OptionKey<?>, Object>> v = new AtomicReference<>();
+
+ private static final EconomicMap<OptionKey<?>, Object> EMPTY_MAP = newOptionMap();
+
+ public ModifiableOptionValues(UnmodifiableEconomicMap<OptionKey<?>, Object> values) {
+ super(EMPTY_MAP);
+ EconomicMap<OptionKey<?>, Object> map = newOptionMap();
+ initMap(map, values);
+ v.set(map);
+ }
+
+ /**
+ * Updates this object with the given key/value pair.
+ */
+ public void update(OptionKey<?> key, Object value) {
+ UnmodifiableEconomicMap<OptionKey<?>, Object> expect;
+ EconomicMap<OptionKey<?>, Object> newMap;
+ do {
+ expect = v.get();
+ newMap = EconomicMap.create(Equivalence.IDENTITY, expect);
+ key.update(newMap, value);
+ // Need to do the null encoding here as `key.update()` doesn't do it
+ newMap.put(key, encodeNull(value));
+ } while (!v.compareAndSet(expect, newMap));
+ }
+
+ /**
+ * Updates this object with the key/value pairs in {@code values}.
+ */
+ public void update(UnmodifiableEconomicMap<OptionKey<?>, Object> values) {
+ if (values.isEmpty()) {
+ return;
+ }
+ UnmodifiableEconomicMap<OptionKey<?>, Object> expect;
+ EconomicMap<OptionKey<?>, Object> newMap;
+ do {
+ expect = v.get();
+ newMap = EconomicMap.create(Equivalence.IDENTITY, expect);
+ UnmodifiableMapCursor<OptionKey<?>, Object> cursor = values.getEntries();
+ while (cursor.advance()) {
+ OptionKey<?> key = cursor.getKey();
+ Object value = cursor.getValue();
+ key.update(newMap, value);
+ // Need to do the null encoding here as `key.update()` doesn't do it
+ newMap.put(key, encodeNull(value));
+ }
+ } while (!v.compareAndSet(expect, newMap));
+ }
+
+ @Override
+ protected <T> T get(OptionKey<T> key) {
+ return OptionValues.get(v.get(), key);
+ }
+
+ @Override
+ protected boolean containsKey(OptionKey<?> key) {
+ return v.get().containsKey(key);
+ }
+
+ @Override
+ public UnmodifiableEconomicMap<OptionKey<?>, Object> getMap() {
+ return v.get();
+ }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java Thu Apr 06 23:01:27 2017 +0000
@@ -33,7 +33,6 @@
import org.graalvm.util.EconomicMap;
import org.graalvm.util.Equivalence;
-import org.graalvm.util.MapCursor;
import org.graalvm.util.UnmodifiableEconomicMap;
import org.graalvm.util.UnmodifiableMapCursor;
@@ -42,25 +41,19 @@
*/
public class OptionValues {
- private final EconomicMap<OptionKey<?>, Object> values = newOptionMap();
+ private final UnmodifiableEconomicMap<OptionKey<?>, Object> values;
- protected OptionValues set(OptionKey<?> key, Object value) {
- values.put(key, encodeNull(value));
- return this;
- }
-
- boolean containsKey(OptionKey<?> key) {
+ protected boolean containsKey(OptionKey<?> key) {
return values.containsKey(key);
}
public OptionValues(OptionValues initialValues, UnmodifiableEconomicMap<OptionKey<?>, Object> extraPairs) {
+ EconomicMap<OptionKey<?>, Object> map = newOptionMap();
if (initialValues != null) {
- values.putAll(initialValues.values);
+ map.putAll(initialValues.values);
}
- UnmodifiableMapCursor<OptionKey<?>, Object> cursor = extraPairs.getEntries();
- while (cursor.advance()) {
- values.put(cursor.getKey(), encodeNull(cursor.getValue()));
- }
+ initMap(map, extraPairs);
+ this.values = map;
}
public OptionValues(OptionValues initialValues, OptionKey<?> key1, Object value1, Object... extraPairs) {
@@ -75,7 +68,8 @@
}
/**
- * Gets an immutable view of the key/value pairs in this object.
+ * Gets an immutable view of the key/value pairs in this object. Values read from this view
+ * should be {@linkplain #decodeNull(Object) decoded} before being used.
*/
public UnmodifiableEconomicMap<OptionKey<?>, Object> getMap() {
return values;
@@ -98,15 +92,25 @@
return map;
}
- public OptionValues(EconomicMap<OptionKey<?>, Object> values) {
- MapCursor<OptionKey<?>, Object> cursor = values.getEntries();
+ public OptionValues(UnmodifiableEconomicMap<OptionKey<?>, Object> values) {
+ EconomicMap<OptionKey<?>, Object> map = newOptionMap();
+ initMap(map, values);
+ this.values = map;
+ }
+
+ protected static void initMap(EconomicMap<OptionKey<?>, Object> map, UnmodifiableEconomicMap<OptionKey<?>, Object> values) {
+ UnmodifiableMapCursor<OptionKey<?>, Object> cursor = values.getEntries();
while (cursor.advance()) {
- this.values.put(cursor.getKey(), encodeNull(cursor.getValue()));
+ map.put(cursor.getKey(), encodeNull(cursor.getValue()));
}
}
+ protected <T> T get(OptionKey<T> key) {
+ return get(values, key);
+ }
+
@SuppressWarnings("unchecked")
- <T> T get(OptionKey<T> key) {
+ protected static <T> T get(UnmodifiableEconomicMap<OptionKey<?>, Object> values, OptionKey<T> key) {
Object value = values.get(key);
if (value == null) {
return key.getDefaultValue();
@@ -116,16 +120,23 @@
private static final Object NULL = new Object();
- private static Object encodeNull(Object value) {
+ protected static Object encodeNull(Object value) {
return value == null ? NULL : value;
}
- private static Object decodeNull(Object value) {
+ /**
+ * Decodes a value that may be the sentinel value for {@code null} in a map.
+ */
+ protected static Object decodeNull(Object value) {
return value == NULL ? null : value;
}
@Override
public String toString() {
+ return toString(getMap());
+ }
+
+ public static String toString(UnmodifiableEconomicMap<OptionKey<?>, Object> values) {
Comparator<OptionKey<?>> comparator = new Comparator<OptionKey<?>>() {
@Override
public int compare(OptionKey<?> o1, OptionKey<?> o2) {
@@ -133,9 +144,9 @@
}
};
SortedMap<OptionKey<?>, Object> sorted = new TreeMap<>(comparator);
- MapCursor<OptionKey<?>, Object> cursor = values.getEntries();
+ UnmodifiableMapCursor<OptionKey<?>, Object> cursor = values.getEntries();
while (cursor.advance()) {
- sorted.put(cursor.getKey(), cursor.getValue());
+ sorted.put(cursor.getKey(), decodeNull(cursor.getValue()));
}
return sorted.toString();
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java Thu Apr 06 23:01:27 2017 +0000
@@ -23,6 +23,7 @@
package org.graalvm.compiler.options;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Formatter;
import java.util.List;
import java.util.ServiceLoader;
@@ -225,13 +226,29 @@
private static List<OptionDescriptor> fuzzyMatch(Iterable<OptionDescriptors> loader, String optionName) {
List<OptionDescriptor> matches = new ArrayList<>();
for (OptionDescriptors options : loader) {
- for (OptionDescriptor option : options) {
- float score = stringSimiliarity(option.getName(), optionName);
- if (score >= FUZZY_MATCH_THRESHOLD) {
- matches.add(option);
- }
- }
+ collectFuzzyMatches(options, optionName, matches);
}
return matches;
}
+
+ /**
+ * Collects the set of options that fuzzy match a given option name. String similarity for fuzzy
+ * matching is based on Dice's coefficient.
+ *
+ * @param toSearch the set of option descriptors to search
+ * @param name the option name to search for
+ * @param matches the collection to which fuzzy matches of {@code name} will be added
+ * @return whether any fuzzy matches were found
+ */
+ public static boolean collectFuzzyMatches(Iterable<OptionDescriptor> toSearch, String name, Collection<OptionDescriptor> matches) {
+ boolean found = false;
+ for (OptionDescriptor option : toSearch) {
+ float score = stringSimiliarity(option.getName(), name);
+ if (score >= FUZZY_MATCH_THRESHOLD) {
+ found = true;
+ matches.add(option);
+ }
+ }
+ return found;
+ }
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/UniquePathUtilities.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/UniquePathUtilities.java Thu Apr 06 23:01:27 2017 +0000
@@ -113,6 +113,6 @@
if (result.isAbsolute() || defaultDirectory == null) {
return result;
}
- return Paths.get(defaultDirectory.getValue(options), name);
+ return Paths.get(defaultDirectory.getValue(options), name).normalize();
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AbstractInliningPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AbstractInliningPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -29,4 +29,8 @@
* Common superclass for phases that perform inlining.
*/
public abstract class AbstractInliningPhase extends BasePhase<HighTierContext> {
+ @Override
+ protected boolean isInliningPhase() {
+ return true;
+ }
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -218,13 +218,13 @@
public void usagesDroppedToZero(Node node) {
workList.add(node);
}
+ };
- };
try (NodeEventScope nes = graph.trackNodeEvents(listener)) {
for (Node n : workList) {
boolean changed = processNode(n);
- if (changed && Debug.isDumpEnabled(Debug.DETAILED_LOG_LEVEL)) {
- Debug.dump(Debug.DETAILED_LOG_LEVEL, graph, "CanonicalizerPhase %s", n);
+ if (changed && Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) {
+ Debug.dump(Debug.DETAILED_LEVEL, graph, "CanonicalizerPhase %s", n);
}
}
}
@@ -329,7 +329,7 @@
}
if (nodeClass.isSimplifiable() && simplify) {
- Debug.log(Debug.VERBOSE_LOG_LEVEL, "Canonicalizer: simplifying %s", node);
+ Debug.log(Debug.VERBOSE_LEVEL, "Canonicalizer: simplifying %s", node);
COUNTER_SIMPLIFICATION_CONSIDERED_NODES.increment();
node.simplify(tool);
return node.isDeleted();
@@ -356,7 +356,7 @@
// @formatter:on
private boolean performReplacement(final Node node, Node newCanonical) {
if (newCanonical == node) {
- Debug.log(Debug.VERBOSE_LOG_LEVEL, "Canonicalizer: work on %1s", node);
+ Debug.log(Debug.VERBOSE_LEVEL, "Canonicalizer: work on %1s", node);
return false;
} else {
Node canonical = newCanonical;
@@ -448,7 +448,7 @@
public void deleteBranch(Node branch) {
FixedNode fixedBranch = (FixedNode) branch;
fixedBranch.predecessor().replaceFirstSuccessor(fixedBranch, null);
- GraphUtil.killCFG(fixedBranch, this);
+ GraphUtil.killCFG(fixedBranch);
}
@Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DominatorConditionalEliminationPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DominatorConditionalEliminationPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -908,6 +908,10 @@
@Override
public Node apply(Node node, Node curNode) {
+ if (!ok) {
+ // Abort the recursion
+ return curNode;
+ }
if (!(curNode instanceof ValueNode)) {
ok = false;
return curNode;
@@ -990,7 +994,7 @@
}
public void pushElement(InfoElement element) {
- Debug.log(Debug.VERBOSE_LOG_LEVEL, "Pushing an info element:%s", element);
+ Debug.log(Debug.VERBOSE_LEVEL, "Pushing an info element:%s", element);
infos.add(element);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LockEliminationPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LockEliminationPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -28,6 +28,7 @@
import org.graalvm.compiler.nodes.java.AccessMonitorNode;
import org.graalvm.compiler.nodes.java.MonitorEnterNode;
import org.graalvm.compiler.nodes.java.MonitorExitNode;
+import org.graalvm.compiler.nodes.java.MonitorIdNode;
import org.graalvm.compiler.nodes.java.RawMonitorEnterNode;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.phases.Phase;
@@ -36,16 +37,25 @@
@Override
protected void run(StructuredGraph graph) {
- for (MonitorExitNode node : graph.getNodes(MonitorExitNode.TYPE)) {
- FixedNode next = node.next();
+ for (MonitorExitNode monitorExitNode : graph.getNodes(MonitorExitNode.TYPE)) {
+ FixedNode next = monitorExitNode.next();
if ((next instanceof MonitorEnterNode || next instanceof RawMonitorEnterNode)) {
// should never happen, osr monitor enters are always direct successors of the graph
// start
assert !(next instanceof OSRMonitorEnterNode);
AccessMonitorNode monitorEnterNode = (AccessMonitorNode) next;
- if (GraphUtil.unproxify(monitorEnterNode.object()) == GraphUtil.unproxify(node.object())) {
+ if (GraphUtil.unproxify(monitorEnterNode.object()) == GraphUtil.unproxify(monitorExitNode.object())) {
+ /*
+ * We've coarsened the lock so use the same monitor id for the whole region,
+ * otherwise the monitor operations appear to be unrelated.
+ */
+ MonitorIdNode enterId = monitorEnterNode.getMonitorId();
+ MonitorIdNode exitId = monitorExitNode.getMonitorId();
+ if (enterId != exitId) {
+ enterId.replaceAndDelete(exitId);
+ }
GraphUtil.removeFixedWithUnusedInputs(monitorEnterNode);
- GraphUtil.removeFixedWithUnusedInputs(node);
+ GraphUtil.removeFixedWithUnusedInputs(monitorExitNode);
}
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/NewConditionalEliminationPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/NewConditionalEliminationPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -135,8 +135,8 @@
}
AbstractBeginNode beginNode = b.getBeginNode();
- if (beginNode instanceof MergeNode && anchorBlock != b) {
- MergeNode mergeNode = (MergeNode) beginNode;
+ if (beginNode instanceof AbstractMergeNode && anchorBlock != b) {
+ AbstractMergeNode mergeNode = (AbstractMergeNode) beginNode;
for (GuardNode guard : mergeNode.guards().snapshot()) {
try (DebugCloseable closeable = guard.withNodeSourcePosition()) {
GuardNode newlyCreatedGuard = new GuardNode(guard.getCondition(), anchorBlock.getBeginNode(), guard.getReason(), guard.getAction(), guard.isNegated(), guard.getSpeculation());
@@ -411,7 +411,7 @@
allow = true;
} else if (integerStamp.asConstant() != null) {
allow = true;
- } else if (oldStamp.unrestricted().equals(oldStamp)) {
+ } else if (oldStamp.isUnrestricted()) {
allow = true;
}
} else {
@@ -432,8 +432,8 @@
if (input == null) {
input = valueAt;
}
- PiNode piNode = graph.unique(new PiNode(input, curBestStamp, (ValueNode) infoElement.guard));
- valueAt = piNode;
+ ValueNode valueNode = graph.maybeAddOrUnique(PiNode.create(input, curBestStamp, (ValueNode) infoElement.guard));
+ valueAt = valueNode;
}
newPhi.addInput(valueAt);
}
@@ -948,6 +948,10 @@
@Override
public Node apply(Node node, Node curNode) {
+ if (!ok) {
+ // Abort the recursion
+ return curNode;
+ }
if (!(curNode instanceof ValueNode)) {
ok = false;
return curNode;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java Thu Apr 06 23:01:27 2017 +0000
@@ -402,7 +402,7 @@
EconomicSet<Node> parameterUsages = calleeInfo.inline(new Providers(context));
canonicalizedNodes.addAll(parameterUsages);
counterInliningRuns.increment();
- Debug.dump(Debug.INFO_LOG_LEVEL, callerGraph, "after %s", calleeInfo);
+ Debug.dump(Debug.DETAILED_LEVEL, callerGraph, "after %s", calleeInfo);
Graph.Mark markBeforeCanonicalization = callerGraph.getMark();
@@ -572,7 +572,7 @@
* Gets the call hierarchy of this inlining from outer most call to inner most callee.
*/
private Object[] inliningContext() {
- if (!Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) {
+ if (!Debug.isDumpEnabled(Debug.INFO_LEVEL)) {
return NO_CONTEXT;
}
Object[] result = new Object[graphQueue.size()];
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -135,6 +135,55 @@
apply(graph, context, true);
}
+ private BasePhase<?> getEnclosingPhase() {
+ for (Object c : Debug.context()) {
+ if (c != this && c instanceof BasePhase) {
+ if (!(c instanceof PhaseSuite)) {
+ return (BasePhase<?>) c;
+ }
+ }
+ }
+ return null;
+ }
+
+ private BasePhase<?> dumpBefore(StructuredGraph graph) {
+ BasePhase<?> enclosingPhase = getEnclosingPhase();
+ boolean isTopLevel = enclosingPhase == null;
+ if (isTopLevel) {
+ if (Debug.isDumpEnabled(Debug.VERBOSE_LEVEL)) {
+ Debug.dump(Debug.VERBOSE_LEVEL, graph, "Before phase %s", getName());
+ }
+ } else {
+ if (Debug.isDumpEnabled(Debug.VERBOSE_LEVEL + 1)) {
+ Debug.dump(Debug.VERBOSE_LEVEL + 1, graph, "Before phase %s", getName());
+ }
+ }
+ return enclosingPhase;
+ }
+
+ protected boolean isInliningPhase() {
+ return false;
+ }
+
+ private void dumpAfter(BasePhase<?> enclosingPhase, StructuredGraph graph) {
+ boolean isTopLevel = enclosingPhase == null;
+ if (isTopLevel) {
+ if (isInliningPhase()) {
+ if (Debug.isDumpEnabled(Debug.BASIC_LEVEL)) {
+ Debug.dump(Debug.BASIC_LEVEL, graph, "After phase %s", getName());
+ }
+ } else {
+ if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) {
+ Debug.dump(Debug.INFO_LEVEL, graph, "After phase %s", getName());
+ }
+ }
+ } else {
+ if (Debug.isDumpEnabled(Debug.INFO_LEVEL + 1)) {
+ Debug.dump(Debug.INFO_LEVEL + 1, graph, "After phase %s", getName());
+ }
+ }
+ }
+
@SuppressWarnings("try")
protected final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) {
graph.checkCancellation();
@@ -149,8 +198,9 @@
before = graph.getMark();
}
}
- if (dumpGraph && Debug.isDumpEnabled(Debug.VERBOSE_LOG_LEVEL)) {
- Debug.dump(Debug.VERBOSE_LOG_LEVEL, graph, "Before phase %s", getName());
+ BasePhase<?> enclosingPhase = null;
+ if (dumpGraph && Debug.isEnabled()) {
+ enclosingPhase = dumpBefore(graph);
}
inputNodesCount.add(graph.getNodeCount());
this.run(graph, context);
@@ -163,8 +213,9 @@
}
}
}
- if (dumpGraph && Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) {
- Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "%s", getName());
+
+ if (dumpGraph && Debug.isEnabled()) {
+ dumpAfter(enclosingPhase, graph);
}
if (Fingerprint.ENABLED) {
String graphDesc = graph.method() == null ? graph.name : graph.method().format("%H.%n(%p)");
@@ -204,5 +255,4 @@
public float codeSizeIncrease() {
return 1.25f;
}
-
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/MergeableState.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/MergeableState.java Thu Apr 06 23:01:27 2017 +0000
@@ -40,7 +40,7 @@
* contains the states of the of the other branches in the order of the merge's end nodes.
*
* @param merge the merge node
- * @param withStates the state at the the merge's end node except the first one.
+ * @param withStates the state at the merge's end node except the first one.
*/
public abstract boolean merge(AbstractMergeNode merge, List<T> withStates);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java Thu Apr 06 23:01:27 2017 +0000
@@ -22,9 +22,19 @@
*/
package org.graalvm.compiler.phases.verify;
+import static org.graalvm.compiler.debug.Debug.BASIC_LEVEL;
+import static org.graalvm.compiler.debug.Debug.DETAILED_LEVEL;
+import static org.graalvm.compiler.debug.Debug.INFO_LEVEL;
+import static org.graalvm.compiler.debug.Debug.VERBOSE_LEVEL;
+import static org.graalvm.compiler.debug.Debug.VERY_DETAILED_LEVEL;
+
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.debug.Debug;
import org.graalvm.compiler.debug.DebugMethodMetrics;
import org.graalvm.compiler.debug.GraalError;
@@ -33,12 +43,16 @@
import org.graalvm.compiler.nodes.CallTargetNode;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.java.NewArrayNode;
import org.graalvm.compiler.nodes.java.StoreIndexedNode;
import org.graalvm.compiler.phases.VerifyPhase;
import org.graalvm.compiler.phases.tiers.PhaseContext;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.PrimitiveConstant;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
@@ -61,20 +75,24 @@
return false;
}
+ MetaAccessProvider metaAccess;
+
@Override
protected boolean verify(StructuredGraph graph, PhaseContext context) {
- ResolvedJavaType debugType = context.getMetaAccess().lookupJavaType(Debug.class);
- ResolvedJavaType nodeType = context.getMetaAccess().lookupJavaType(Node.class);
- ResolvedJavaType stringType = context.getMetaAccess().lookupJavaType(String.class);
- ResolvedJavaType debugMethodMetricsType = context.getMetaAccess().lookupJavaType(DebugMethodMetrics.class);
- ResolvedJavaType graalErrorType = context.getMetaAccess().lookupJavaType(GraalError.class);
+ metaAccess = context.getMetaAccess();
+ ResolvedJavaType debugType = metaAccess.lookupJavaType(Debug.class);
+ ResolvedJavaType nodeType = metaAccess.lookupJavaType(Node.class);
+ ResolvedJavaType stringType = metaAccess.lookupJavaType(String.class);
+ ResolvedJavaType debugMethodMetricsType = metaAccess.lookupJavaType(DebugMethodMetrics.class);
+ ResolvedJavaType graalErrorType = metaAccess.lookupJavaType(GraalError.class);
for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) {
ResolvedJavaMethod callee = t.targetMethod();
String calleeName = callee.getName();
if (callee.getDeclaringClass().equals(debugType)) {
- if (calleeName.equals("log") || calleeName.equals("logAndIndent") || calleeName.equals("verify") || calleeName.equals("dump")) {
- verifyParameters(t, graph, t.arguments(), stringType, calleeName.equals("dump") ? 2 : 1);
+ boolean isDump = calleeName.equals("dump");
+ if (calleeName.equals("log") || calleeName.equals("logAndIndent") || calleeName.equals("verify") || isDump) {
+ verifyParameters(t, graph, t.arguments(), stringType, isDump ? 2 : 1);
}
}
if (callee.getDeclaringClass().isAssignableFrom(nodeType)) {
@@ -99,10 +117,10 @@
return true;
}
- private static void verifyParameters(MethodCallTargetNode callTarget, StructuredGraph callerGraph, NodeInputList<? extends Node> args, ResolvedJavaType stringType, int startArgIdx) {
+ private void verifyParameters(MethodCallTargetNode callTarget, StructuredGraph callerGraph, NodeInputList<? extends ValueNode> args, ResolvedJavaType stringType, int startArgIdx) {
if (callTarget.targetMethod().isVarArgs() && args.get(args.count() - 1) instanceof NewArrayNode) {
// unpack the arguments to the var args
- List<Node> unpacked = new ArrayList<>(args.snapshot());
+ List<ValueNode> unpacked = new ArrayList<>(args.snapshot());
NewArrayNode varArgParameter = (NewArrayNode) unpacked.remove(unpacked.size() - 1);
int firstVarArg = unpacked.size();
for (Node usage : varArgParameter.usages()) {
@@ -111,18 +129,57 @@
unpacked.add(si.value());
}
}
- verifyParameters(callerGraph, callTarget.targetMethod(), unpacked, stringType, startArgIdx, firstVarArg);
+ verifyParameters(callerGraph, callTarget, unpacked, stringType, startArgIdx, firstVarArg);
} else {
- verifyParameters(callerGraph, callTarget.targetMethod(), args, stringType, startArgIdx, -1);
+ verifyParameters(callerGraph, callTarget, args, stringType, startArgIdx, -1);
}
}
- private static void verifyParameters(StructuredGraph callerGraph, ResolvedJavaMethod verifiedCallee, List<? extends Node> args, ResolvedJavaType stringType, int startArgIdx, int varArgsIndex) {
+ private static final Set<Integer> DebugLevels = new HashSet<>(Arrays.asList(BASIC_LEVEL, INFO_LEVEL, VERBOSE_LEVEL, DETAILED_LEVEL, VERY_DETAILED_LEVEL));
+
+ /**
+ * The set of methods allowed to call a {@code Debug.dump(...)} method with the {@code level}
+ * parameter bound to {@link Debug#BASIC_LEVEL} and the {@code object} parameter bound to a
+ * {@link StructuredGraph} value.
+ *
+ * This whitelist exists to ensure any increase in graph dumps is in line with the policy
+ * outlined by {@link Debug#BASIC_LEVEL}. If you add a *justified* graph dump at this level,
+ * then update the whitelist.
+ */
+ private static final Set<String> BasicLevelStructuredGraphDumpWhitelist = new HashSet<>(Arrays.asList(
+ "org.graalvm.compiler.phases.BasePhase.dumpAfter",
+ "org.graalvm.compiler.core.GraalCompiler.emitFrontEnd",
+ "org.graalvm.compiler.truffle.PartialEvaluator.fastPartialEvaluation",
+ "org.graalvm.compiler.truffle.PartialEvaluator.reportPerformanceWarnings",
+ "org.graalvm.compiler.truffle.TruffleCompiler.compileMethodHelper",
+ "org.graalvm.compiler.core.test.VerifyDebugUsageTest$ValidDumpUsagePhase.run",
+ "org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidConcatDumpUsagePhase.run",
+ "org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidDumpUsagePhase.run"));
+
+ /**
+ * The set of methods allowed to call a {@code Debug.dump(...)} method with the {@code level}
+ * parameter bound to {@link Debug#INFO_LEVEL} and the {@code object} parameter bound to a
+ * {@link StructuredGraph} value.
+ *
+ * This whitelist exists to ensure any increase in graph dumps is in line with the policy
+ * outlined by {@link Debug#INFO_LEVEL}. If you add a *justified* graph dump at this level, then
+ * update the whitelist.
+ */
+ private static final Set<String> InfoLevelStructuredGraphDumpWhitelist = new HashSet<>(Arrays.asList(
+ "org.graalvm.compiler.core.GraalCompiler.emitFrontEnd",
+ "org.graalvm.compiler.phases.BasePhase.dumpAfter",
+ "org.graalvm.compiler.replacements.ReplacementsImpl$GraphMaker.makeGraph",
+ "org.graalvm.compiler.replacements.SnippetTemplate.instantiate"));
+
+ private void verifyParameters(StructuredGraph callerGraph, MethodCallTargetNode debugCallTarget, List<? extends ValueNode> args, ResolvedJavaType stringType, int startArgIdx,
+ int varArgsIndex) {
+ ResolvedJavaMethod verifiedCallee = debugCallTarget.targetMethod();
+ Integer dumpLevel = null;
int argIdx = startArgIdx;
int varArgsElementIndex = 0;
boolean reportVarArgs = false;
for (int i = 0; i < args.size(); i++) {
- Node arg = args.get(i);
+ ValueNode arg = args.get(i);
if (arg instanceof Invoke) {
reportVarArgs = varArgsIndex >= 0 && argIdx >= varArgsIndex;
Invoke invoke = (Invoke) arg;
@@ -142,6 +199,15 @@
}
}
}
+ if (i == 0) {
+ if (verifiedCallee.getName().equals("dump")) {
+ dumpLevel = verifyDumpLevelParameter(callerGraph, debugCallTarget, verifiedCallee, arg);
+ }
+ } else if (i == 1) {
+ if (dumpLevel != null) {
+ verifyDumpObjectParameter(callerGraph, debugCallTarget, args, verifiedCallee, dumpLevel);
+ }
+ }
if (varArgsIndex >= 0 && i >= varArgsIndex) {
varArgsElementIndex++;
}
@@ -150,6 +216,63 @@
}
/**
+ * The {@code level} arg for the {@code Debug.dump(...)} methods must be a reference to one of
+ * the {@code Debug.*_LEVEL} constants.
+ */
+ protected Integer verifyDumpLevelParameter(StructuredGraph callerGraph, MethodCallTargetNode debugCallTarget, ResolvedJavaMethod verifiedCallee, ValueNode arg)
+ throws org.graalvm.compiler.phases.VerifyPhase.VerificationError {
+ // The 'level' arg for the Debug.dump(...) methods must be a reference to one of
+ // the Debug.*_LEVEL constants.
+
+ Constant c = arg.asConstant();
+ if (c != null) {
+ Integer dumpLevel = ((PrimitiveConstant) c).asInt();
+ if (!DebugLevels.contains(dumpLevel)) {
+ StackTraceElement e = callerGraph.method().asStackTraceElement(debugCallTarget.invoke().bci());
+ throw new VerificationError(
+ "In %s: parameter 0 of call to %s does not match a Debug.*_LEVEL constant.%n", e, verifiedCallee.format("%H.%n(%p)"));
+ }
+ return dumpLevel;
+ }
+ StackTraceElement e = callerGraph.method().asStackTraceElement(debugCallTarget.invoke().bci());
+ throw new VerificationError(
+ "In %s: parameter 0 of call to %s must be a constant.%n", e, verifiedCallee.format("%H.%n(%p)"));
+ }
+
+ protected void verifyDumpObjectParameter(StructuredGraph callerGraph, MethodCallTargetNode debugCallTarget, List<? extends ValueNode> args, ResolvedJavaMethod verifiedCallee, Integer dumpLevel)
+ throws org.graalvm.compiler.phases.VerifyPhase.VerificationError {
+ ResolvedJavaType arg1Type = ((ObjectStamp) args.get(1).stamp()).type();
+ if (metaAccess.lookupJavaType(StructuredGraph.class).isAssignableFrom(arg1Type)) {
+ verifyStructuredGraphDumping(callerGraph, debugCallTarget, verifiedCallee, dumpLevel);
+ }
+ }
+
+ /**
+ * Verifies that dumping a {@link StructuredGraph} at level {@link Debug#BASIC_LEVEL} or
+ * {@link Debug#INFO_LEVEL} only occurs in white-listed methods.
+ */
+ protected void verifyStructuredGraphDumping(StructuredGraph callerGraph, MethodCallTargetNode debugCallTarget, ResolvedJavaMethod verifiedCallee, Integer dumpLevel)
+ throws org.graalvm.compiler.phases.VerifyPhase.VerificationError {
+ if (dumpLevel == Debug.BASIC_LEVEL) {
+ StackTraceElement e = callerGraph.method().asStackTraceElement(debugCallTarget.invoke().bci());
+ String qualifiedMethod = e.getClassName() + "." + e.getMethodName();
+ if (!BasicLevelStructuredGraphDumpWhitelist.contains(qualifiedMethod)) {
+ throw new VerificationError(
+ "In %s: call to %s with level == Debug.BASIC_LEVEL not in %s.BasicLevelDumpWhitelist.%n", e, verifiedCallee.format("%H.%n(%p)"),
+ getClass().getName());
+ }
+ } else if (dumpLevel == Debug.INFO_LEVEL) {
+ StackTraceElement e = callerGraph.method().asStackTraceElement(debugCallTarget.invoke().bci());
+ String qualifiedMethod = e.getClassName() + "." + e.getMethodName();
+ if (!InfoLevelStructuredGraphDumpWhitelist.contains(qualifiedMethod)) {
+ throw new VerificationError(
+ "In %s: call to %s with level == Debug.INFO_LEVEL not in %s.InfoLevelDumpWhitelist.%n", e, verifiedCallee.format("%H.%n(%p)"),
+ getClass().getName());
+ }
+ }
+ }
+
+ /**
* Checks that a given call is not to {@link StringBuffer#toString()} or
* {@link StringBuilder#toString()}.
*/
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java Thu Apr 06 23:01:27 2017 +0000
@@ -158,7 +158,7 @@
} else if (isToStringTrusted(c)) {
return value.toString();
}
- return MetaUtil.getSimpleName(c, true) + "@" + System.identityHashCode(value);
+ return MetaUtil.getSimpleName(c, true) + "@" + Integer.toHexString(System.identityHashCode(value));
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java Thu Apr 06 23:01:27 2017 +0000
@@ -173,6 +173,9 @@
Map<Object, Object> properties = new HashMap<>();
properties.put("graph", graph.toString());
properties.put("scope", Debug.currentScope());
+ if (graph instanceof StructuredGraph) {
+ properties.put("compilationIdentifier", ((StructuredGraph) graph).compilationId());
+ }
addCFGFileName(properties);
printer.print(graph, nextDumpId() + ":" + message, properties);
} catch (IOException e) {
@@ -298,7 +301,6 @@
}
private void openScope(String name, int inlineDepth, Map<Object, Object> properties) {
- String prefix = inlineDepth == 0 ? Thread.currentThread().getName() + ":" : "";
try {
Map<Object, Object> props = properties;
if (inlineDepth == 0) {
@@ -312,7 +314,7 @@
}
props.put("date", new Date().toString());
}
- printer.beginGroup(prefix + name, name, Debug.contextLookup(ResolvedJavaMethod.class), -1, props);
+ printer.beginGroup(name, name, Debug.contextLookup(ResolvedJavaMethod.class), -1, props);
} catch (IOException e) {
handleException(e);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/InstanceOfTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/InstanceOfTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -488,7 +488,7 @@
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);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -56,9 +56,9 @@
try (Scope s = Debug.scope("MethodSubstitutionTest", getResolvedJavaMethod(snippet))) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
HighTierContext context = getDefaultHighTierContext();
- Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
+ Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
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);
// Try to ensure any macro nodes are lowered to expose any resulting invokes
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -133,11 +133,12 @@
try (Debug.Scope scope = Debug.scope("GraphPETest", testMethod)) {
GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withEagerResolving(true);
registerPlugins(graphBuilderConfig.getPlugins().getInvocationPlugins());
- CachingPEGraphDecoder decoder = new CachingPEGraphDecoder(getProviders(), graphBuilderConfig, OptimisticOptimizations.NONE, AllowAssumptions.YES, getTarget().arch, getInitialOptions());
+ targetGraph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.YES).method(testMethod).build();
+ CachingPEGraphDecoder decoder = new CachingPEGraphDecoder(getTarget().arch, targetGraph, getProviders(), graphBuilderConfig, OptimisticOptimizations.NONE, AllowAssumptions.YES,
+ getInitialOptions(), null, null, new InlineInvokePlugin[]{new InlineAll()}, null);
- targetGraph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.YES).method(testMethod).build();
- decoder.decode(targetGraph, testMethod, null, null, new InlineInvokePlugin[]{new InlineAll()}, null);
- Debug.dump(Debug.BASIC_LOG_LEVEL, targetGraph, "Target Graph");
+ decoder.decode(testMethod);
+ Debug.dump(Debug.BASIC_LEVEL, targetGraph, "Target Graph");
targetGraph.verify();
PhaseContext context = new PhaseContext(getProviders());
@@ -146,7 +147,7 @@
} catch (Throwable ex) {
if (targetGraph != null) {
- Debug.dump(Debug.BASIC_LOG_LEVEL, targetGraph, ex.toString());
+ Debug.dump(Debug.BASIC_LEVEL, targetGraph, ex.toString());
}
Debug.handle(ex);
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionsTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionsTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -133,7 +133,7 @@
@Override
protected Plugins getDefaultGraphBuilderPlugins() {
Plugins ret = super.getDefaultGraphBuilderPlugins();
- // manually register generated factories, jvmci service providers don't work from unit tests
+ // manually register generated factories, Graal service providers don't work from unit tests
new PluginFactory_SubstitutionsTest().registerPlugins(ret.getInvocationPlugins(), null);
return ret;
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/GeneratedNodeIntrinsicPlugin.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/GeneratedNodeIntrinsicPlugin.java Thu Apr 06 23:01:27 2017 +0000
@@ -32,12 +32,10 @@
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
-import javax.tools.Diagnostic.Kind;
import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
import org.graalvm.compiler.graph.Node.InjectedNodeParameter;
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
-import org.graalvm.compiler.replacements.verifier.InjectedDependencies.WellKnownDependency;
/**
* Create graph builder plugins for {@link NodeIntrinsic} methods.
@@ -124,10 +122,6 @@
}
out.printf(");\n");
- if (intrinsicMethod.getAnnotation(NodeIntrinsic.class).setStampFromReturnType()) {
- out.printf(" node.setStamp(%s);\n", deps.use(WellKnownDependency.RETURN_STAMP));
- }
-
if (intrinsicMethod.getReturnType().getKind() == TypeKind.VOID) {
out.printf(" b.add(node);\n");
} else {
@@ -164,10 +158,6 @@
out.printf(", arg%d", i);
}
out.printf(");\n");
-
- if (intrinsicMethod.getAnnotation(NodeIntrinsic.class).setStampFromReturnType()) {
- env.getMessager().printMessage(Kind.WARNING, "Ignoring setStampFromReturnType because a custom 'intrinsify' method is used.", intrinsicMethod);
- }
}
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/InjectedDependencies.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/InjectedDependencies.java Thu Apr 06 23:01:27 2017 +0000
@@ -60,23 +60,24 @@
}
}
- private static final class StampDependency extends Dependency {
+ private static final class InjectedStampDependency extends Dependency {
- private StampDependency() {
- super("returnStamp", "org.graalvm.compiler.core.common.type.Stamp");
+ private InjectedStampDependency() {
+ super("stamp", "org.graalvm.compiler.core.common.type.Stamp");
}
@Override
public String inject(ExecutableElement inject) {
NodeIntrinsic nodeIntrinsic = inject.getAnnotation(NodeIntrinsic.class);
- return String.format("injection.getReturnStamp(%s.class, %s)", GeneratedPlugin.getErasedType(inject.getReturnType()), nodeIntrinsic != null && nodeIntrinsic.returnStampIsNonNull());
+ boolean nonNull = nodeIntrinsic != null && nodeIntrinsic.injectedStampIsNonNull();
+ return String.format("injection.getInjectedStamp(%s.class, %s)", GeneratedPlugin.getErasedType(inject.getReturnType()), nonNull);
}
}
public enum WellKnownDependency {
CONSTANT_REFLECTION("b.getConstantReflection()", "jdk.vm.ci.meta.ConstantReflectionProvider"),
META_ACCESS("b.getMetaAccess()", "jdk.vm.ci.meta.MetaAccessProvider"),
- RETURN_STAMP(new StampDependency()),
+ INJECTED_STAMP(new InjectedStampDependency()),
SNIPPET_REFLECTION(new InjectedDependency("snippetReflection", "org.graalvm.compiler.api.replacements.SnippetReflectionProvider")),
STAMP_PROVIDER("b.getStampProvider()", "org.graalvm.compiler.nodes.spi.StampProvider"),
STRUCTURED_GRAPH("b.getGraph()", "org.graalvm.compiler.nodes.StructuredGraph");
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/NodeIntrinsicVerifier.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.verifier/src/org/graalvm/compiler/replacements/verifier/NodeIntrinsicVerifier.java Thu Apr 06 23:01:27 2017 +0000
@@ -25,7 +25,11 @@
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.Formatter;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
@@ -57,6 +61,10 @@
return env.getElementUtils().getTypeElement("org.graalvm.compiler.graph.Node").asType();
}
+ private TypeMirror stampType() {
+ return env.getElementUtils().getTypeElement("org.graalvm.compiler.core.common.type.Stamp").asType();
+ }
+
private TypeMirror valueNodeType() {
return env.getElementUtils().getTypeElement("org.graalvm.compiler.nodes.ValueNode").asType();
}
@@ -118,32 +126,68 @@
}
}
- if (intrinsicMethod.getReturnType() instanceof TypeVariable) {
+ TypeMirror returnType = intrinsicMethod.getReturnType();
+ if (returnType instanceof TypeVariable) {
env.getMessager().printMessage(Kind.ERROR, "@NodeIntrinsic cannot have a generic return type.", element, annotation);
}
+ boolean injectedStampIsNonNull = intrinsicMethod.getAnnotation(NodeIntrinsic.class).injectedStampIsNonNull();
+
+ if (returnType.getKind() == TypeKind.VOID) {
+ for (VariableElement parameter : intrinsicMethod.getParameters()) {
+ if (parameter.getAnnotation(InjectedNodeParameter.class) != null) {
+ env.getMessager().printMessage(Kind.ERROR, "@NodeIntrinsic with an injected Stamp parameter cannot have a void return type.", element, annotation);
+ break;
+ }
+ }
+ }
+
TypeMirror[] constructorSignature = constructorSignature(intrinsicMethod);
- ExecutableElement custom = findCustomIntrinsifyMethod(nodeClass, constructorSignature);
- if (custom != null) {
- generator.addPlugin(new GeneratedNodeIntrinsicPlugin.CustomFactoryPlugin(intrinsicMethod, custom, constructorSignature));
+ Map<ExecutableElement, String> nonMatches = new HashMap<>();
+ List<ExecutableElement> factories = findIntrinsifyFactoryMethod(nodeClass, constructorSignature, nonMatches, injectedStampIsNonNull);
+ List<ExecutableElement> constructors = Collections.emptyList();
+ if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) {
+ if (factories.isEmpty()) {
+ env.getMessager().printMessage(Kind.ERROR, String.format("Cannot make a node intrinsic for an abstract class %s.", nodeClass.getSimpleName()), element, annotation);
+ }
+ } else if (!isNodeType(nodeClass)) {
+ if (factories.isEmpty()) {
+ env.getMessager().printMessage(Kind.ERROR, String.format("%s is not a subclass of %s.", nodeClass.getSimpleName(), nodeType()), element, annotation);
+ }
} else {
- if (isNodeType(nodeClass)) {
- if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) {
- env.getMessager().printMessage(Kind.ERROR, String.format("Cannot make @NodeIntrinsic for abstract node class %s.", nodeClass.getSimpleName()), element, annotation);
- } else {
- TypeMirror ret = intrinsicMethod.getReturnType();
- if (env.getTypeUtils().isAssignable(ret, structuralInputType())) {
- checkInputType(nodeClass, ret, element, annotation);
- }
+ TypeMirror ret = returnType;
+ if (env.getTypeUtils().isAssignable(ret, structuralInputType())) {
+ checkInputType(nodeClass, ret, element, annotation);
+ }
- ExecutableElement constructor = findConstructor(nodeClass, constructorSignature, intrinsicMethod, annotation);
- if (constructor != null) {
- generator.addPlugin(new GeneratedNodeIntrinsicPlugin.ConstructorPlugin(intrinsicMethod, constructor, constructorSignature));
- }
+ constructors = findConstructors(nodeClass, constructorSignature, nonMatches, injectedStampIsNonNull);
+ }
+ Formatter msg = new Formatter();
+ if (factories.size() > 1) {
+ msg.format("Found more than one factory in %s matching node intrinsic:", nodeClass);
+ for (ExecutableElement candidate : factories) {
+ msg.format("%n %s", candidate);
+ }
+ env.getMessager().printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation);
+ } else if (constructors.size() > 1) {
+ msg.format("Found more than one constructor in %s matching node intrinsic:", nodeClass);
+ for (ExecutableElement candidate : constructors) {
+ msg.format("%n %s", candidate);
+ }
+ env.getMessager().printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation);
+ } else if (factories.size() == 1) {
+ generator.addPlugin(new GeneratedNodeIntrinsicPlugin.CustomFactoryPlugin(intrinsicMethod, factories.get(0), constructorSignature));
+ } else if (constructors.size() == 1) {
+ generator.addPlugin(new GeneratedNodeIntrinsicPlugin.ConstructorPlugin(intrinsicMethod, constructors.get(0), constructorSignature));
+ } else {
+ msg.format("Could not find any factories or constructors in %s matching node intrinsic", nodeClass);
+ if (!nonMatches.isEmpty()) {
+ msg.format("%nFactories and constructors that failed to match:");
+ for (Map.Entry<ExecutableElement, String> e : nonMatches.entrySet()) {
+ msg.format("%n %s: %s", e.getKey(), e.getValue());
}
- } else {
- env.getMessager().printMessage(Kind.ERROR, String.format("The class %s is not a Node subclass.", nodeClass.getSimpleName()), element, annotation);
}
+ env.getMessager().printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation);
}
}
@@ -201,34 +245,20 @@
return parameters;
}
- private ExecutableElement findConstructor(TypeElement nodeClass, TypeMirror[] signature, ExecutableElement intrinsicMethod, AnnotationMirror intrinsicAnnotation) {
+ private List<ExecutableElement> findConstructors(TypeElement nodeClass, TypeMirror[] signature, Map<ExecutableElement, String> nonMatches, boolean requiresInjectedStamp) {
List<ExecutableElement> constructors = ElementFilter.constructorsIn(nodeClass.getEnclosedElements());
- List<String> failureReasons = new ArrayList<>();
-
+ List<ExecutableElement> found = new ArrayList<>(constructors.size());
for (ExecutableElement constructor : constructors) {
- String failureReason = matchSignature(0, constructor, signature);
- if (failureReason == null) {
- // found
- return constructor;
- }
-
- failureReasons.add(failureReason);
- }
-
- // not found
- if (failureReasons.isEmpty()) {
- env.getMessager().printMessage(Kind.ERROR, "Could not find matching constructor for node intrinsic.", intrinsicMethod, intrinsicAnnotation);
- } else {
- for (String reason : failureReasons) {
- env.getMessager().printMessage(Kind.ERROR, reason, intrinsicMethod, intrinsicAnnotation);
+ if (matchSignature(0, constructor, signature, nonMatches, requiresInjectedStamp)) {
+ found.add(constructor);
}
}
-
- return null;
+ return found;
}
- private ExecutableElement findCustomIntrinsifyMethod(TypeElement nodeClass, TypeMirror[] signature) {
+ private List<ExecutableElement> findIntrinsifyFactoryMethod(TypeElement nodeClass, TypeMirror[] signature, Map<ExecutableElement, String> nonMatches, boolean requiresInjectedStamp) {
List<ExecutableElement> methods = ElementFilter.methodsIn(nodeClass.getEnclosedElements());
+ List<ExecutableElement> found = new ArrayList<>(methods.size());
for (ExecutableElement method : methods) {
if (!method.getSimpleName().toString().equals("intrinsify")) {
continue;
@@ -248,50 +278,64 @@
continue;
}
- String failureReason = matchSignature(2, method, signature);
- if (failureReason == null) {
- // found
- return method;
+ if (method.getReturnType().getKind() != TypeKind.BOOLEAN) {
+ continue;
+ }
+
+ if (matchSignature(2, method, signature, nonMatches, requiresInjectedStamp)) {
+ found.add(method);
}
}
-
- return null;
+ return found;
}
- private String matchSignature(int numSkippedParameters, ExecutableElement method, TypeMirror[] signature) {
+ private boolean matchSignature(int numSkippedParameters, ExecutableElement method, TypeMirror[] signature, Map<ExecutableElement, String> nonMatches, boolean requiresInjectedStamp) {
int sIdx = 0;
int cIdx = numSkippedParameters;
+ boolean missingStampArgument = requiresInjectedStamp;
while (cIdx < method.getParameters().size()) {
VariableElement parameter = method.getParameters().get(cIdx++);
+ TypeMirror paramType = parameter.asType();
if (parameter.getAnnotation(InjectedNodeParameter.class) != null) {
+ if (missingStampArgument && env.getTypeUtils().isSameType(paramType, stampType())) {
+ missingStampArgument = false;
+ }
// skip injected parameters
continue;
}
+ if (missingStampArgument) {
+ nonMatches.put(method, String.format("missing injected %s argument", stampType()));
+ return false;
+ }
- TypeMirror paramType = parameter.asType();
if (cIdx == method.getParameters().size() && paramType.getKind() == TypeKind.ARRAY) {
// last argument of constructor is varargs, match remaining intrinsic arguments
TypeMirror varargsType = ((ArrayType) paramType).getComponentType();
while (sIdx < signature.length) {
if (!isTypeCompatible(varargsType, signature[sIdx++])) {
- return String.format("%s failed because the types of argument %d are incompatible: %s != %s", method, sIdx, varargsType, signature[sIdx - 1]);
+ nonMatches.put(method, String.format("the types of argument %d are incompatible: %s != %s", sIdx, varargsType, signature[sIdx - 1]));
+ return false;
}
}
} else if (sIdx >= signature.length) {
// too many arguments in intrinsic method
- return String.format("Too many arguments for %s", method);
+ nonMatches.put(method, "too many arguments");
+ return false;
} else if (!isTypeCompatible(paramType, signature[sIdx++])) {
- return String.format("%s failed because the types of argument %d are incompatible: %s != %s", method, sIdx, paramType, signature[sIdx - 1]);
+ nonMatches.put(method, String.format("the type of argument %d is incompatible: %s != %s", sIdx, paramType, signature[sIdx - 1]));
+ return false;
}
}
+ if (missingStampArgument) {
+ nonMatches.put(method, String.format("missing injected %s argument", stampType()));
+ return false;
+ }
- if (sIdx == signature.length) {
- // found
- return null;
+ if (sIdx != signature.length) {
+ nonMatches.put(method, "not enough arguments");
+ return false;
}
-
- // too many arguments in constructor
- return String.format("Not enough arguments for %s", method);
+ return true;
}
private boolean isTypeCompatible(TypeMirror originalType, TypeMirror substitutionType) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java Thu Apr 06 23:01:27 2017 +0000
@@ -32,7 +32,11 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
+import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
@@ -56,9 +60,11 @@
private final AllowAssumptions allowAssumptions;
private final EconomicMap<ResolvedJavaMethod, EncodedGraph> graphCache;
- public CachingPEGraphDecoder(Providers providers, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, AllowAssumptions allowAssumptions,
- Architecture architecture, OptionValues options) {
- super(providers.getMetaAccess(), providers.getConstantReflection(), providers.getConstantFieldProvider(), providers.getStampProvider(), architecture, options);
+ public CachingPEGraphDecoder(Architecture architecture, StructuredGraph graph, Providers providers, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts,
+ AllowAssumptions allowAssumptions, OptionValues options, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin[] inlineInvokePlugins,
+ ParameterPlugin parameterPlugin) {
+ super(architecture, graph, providers.getMetaAccess(), providers.getConstantReflection(), providers.getConstantFieldProvider(), providers.getStampProvider(), options, loopExplosionPlugin,
+ invocationPlugins, inlineInvokePlugins, parameterPlugin);
this.providers = providers;
this.graphBuilderConfig = graphBuilderConfig;
@@ -74,22 +80,22 @@
@SuppressWarnings("try")
private EncodedGraph createGraph(ResolvedJavaMethod method, BytecodeProvider intrinsicBytecodeProvider) {
- StructuredGraph graph = new StructuredGraph.Builder(options, allowAssumptions).useProfilingInfo(false).method(method).build();
- try (Debug.Scope scope = Debug.scope("createGraph", graph)) {
+ StructuredGraph graphToEncode = new StructuredGraph.Builder(options, allowAssumptions).useProfilingInfo(false).method(method).build();
+ try (Debug.Scope scope = Debug.scope("createGraph", graphToEncode)) {
IntrinsicContext initialIntrinsicContext = intrinsicBytecodeProvider != null ? new IntrinsicContext(method, method, intrinsicBytecodeProvider, INLINE_AFTER_PARSING) : null;
GraphBuilderPhase.Instance graphBuilderPhaseInstance = createGraphBuilderPhaseInstance(initialIntrinsicContext);
- graphBuilderPhaseInstance.apply(graph);
+ graphBuilderPhaseInstance.apply(graphToEncode);
PhaseContext context = new PhaseContext(providers);
- new CanonicalizerPhase().apply(graph, context);
+ new CanonicalizerPhase().apply(graphToEncode, context);
/*
* ConvertDeoptimizeToGuardPhase reduces the number of merges in the graph, so that
* fewer frame states will be created. This significantly reduces the number of nodes in
* the initial graph.
*/
- new ConvertDeoptimizeToGuardPhase().apply(graph, context);
+ new ConvertDeoptimizeToGuardPhase().apply(graphToEncode, context);
- EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, architecture);
+ EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graphToEncode, architecture);
graphCache.put(method, encodedGraph);
return encodedGraph;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Thu Apr 06 23:01:27 2017 +0000
@@ -44,7 +44,6 @@
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
import org.graalvm.compiler.core.common.type.IntegerStamp;
-import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
@@ -78,11 +77,11 @@
import org.graalvm.compiler.nodes.extended.JavaWriteNode;
import org.graalvm.compiler.nodes.extended.LoadHubNode;
import org.graalvm.compiler.nodes.extended.MembarNode;
+import org.graalvm.compiler.nodes.extended.RawLoadNode;
+import org.graalvm.compiler.nodes.extended.RawStoreNode;
import org.graalvm.compiler.nodes.extended.UnboxNode;
-import org.graalvm.compiler.nodes.extended.RawLoadNode;
import org.graalvm.compiler.nodes.extended.UnsafeMemoryLoadNode;
import org.graalvm.compiler.nodes.extended.UnsafeMemoryStoreNode;
-import org.graalvm.compiler.nodes.extended.RawStoreNode;
import org.graalvm.compiler.nodes.java.AbstractNewObjectNode;
import org.graalvm.compiler.nodes.java.AccessIndexedNode;
import org.graalvm.compiler.nodes.java.ArrayLengthNode;
@@ -374,7 +373,7 @@
*/
public AddressNode createArrayIndexAddress(StructuredGraph graph, ValueNode array, JavaKind elementKind, ValueNode index, GuardingNode boundsCheck) {
IntegerStamp indexStamp = StampFactory.forInteger(32, 0, Integer.MAX_VALUE - 1);
- ValueNode positiveIndex = graph.unique(new PiNode(index, indexStamp, boundsCheck != null ? boundsCheck.asNode() : null));
+ ValueNode positiveIndex = graph.maybeAddOrUnique(PiNode.create(index, indexStamp, boundsCheck != null ? boundsCheck.asNode() : null));
return createArrayAddress(graph, array, elementKind, positiveIndex);
}
@@ -961,7 +960,7 @@
arrayLength = arrayLength.isAlive() ? arrayLength : graph.addOrUniqueWithInputs(arrayLength);
}
- LogicNode boundsCheck = IntegerBelowNode.create(n.index(), arrayLength, tool.getConstantReflection());
+ LogicNode boundsCheck = IntegerBelowNode.create(n.index(), arrayLength);
if (boundsCheck.isTautology()) {
return null;
} else {
@@ -981,7 +980,7 @@
if (nullCheck == null) {
return object;
} else {
- return before.graph().unique(new PiNode(object, ((ObjectStamp) object.stamp()).join(StampFactory.objectNonNull()), (ValueNode) nullCheck));
+ return before.graph().maybeAddOrUnique(PiNode.create(object, (object.stamp()).join(StampFactory.objectNonNull()), (ValueNode) nullCheck));
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java Thu Apr 06 23:01:27 2017 +0000
@@ -358,7 +358,7 @@
* {@link #endIf} to close the if-block.
*
* @param condition The condition for the if-block
- * @param trueProbability The estimated probability the the condition is true
+ * @param trueProbability The estimated probability the condition is true
*/
public void startIf(LogicNode condition, double trueProbability) {
AbstractBeginNode thenSuccessor = graph.add(new BeginNode());
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java Thu Apr 06 23:01:27 2017 +0000
@@ -50,7 +50,7 @@
}
@Override
- public Stamp getReturnStamp(Class<?> type, boolean nonNull) {
+ public Stamp getInjectedStamp(Class<?> type, boolean nonNull) {
JavaKind kind = JavaKind.fromJavaClass(type);
if (kind == JavaKind.Object) {
ResolvedJavaType returnType = metaAccess.lookupJavaType(type);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java Thu Apr 06 23:01:27 2017 +0000
@@ -23,14 +23,12 @@
package org.graalvm.compiler.replacements;
import static org.graalvm.compiler.debug.GraalError.unimplemented;
-import static org.graalvm.compiler.java.BytecodeParserOptions.DumpDuringGraphBuilding;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -54,6 +52,7 @@
import org.graalvm.compiler.nodes.AbstractMergeNode;
import org.graalvm.compiler.nodes.CallTargetNode;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
+import org.graalvm.compiler.nodes.ControlSinkNode;
import org.graalvm.compiler.nodes.DeoptimizeNode;
import org.graalvm.compiler.nodes.EncodedGraph;
import org.graalvm.compiler.nodes.FixedNode;
@@ -137,10 +136,6 @@
protected final InvokeData invokeData;
protected final int inliningDepth;
- protected final LoopExplosionPlugin loopExplosionPlugin;
- protected final InvocationPlugins invocationPlugins;
- protected final InlineInvokePlugin[] inlineInvokePlugins;
- protected final ParameterPlugin parameterPlugin;
protected final ValueNode[] arguments;
protected FrameState outerState;
@@ -149,21 +144,17 @@
protected NodeSourcePosition callerBytecodePosition;
protected PEMethodScope(StructuredGraph targetGraph, PEMethodScope caller, LoopScope callerLoopScope, EncodedGraph encodedGraph, ResolvedJavaMethod method, InvokeData invokeData,
- int inliningDepth, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin[] inlineInvokePlugins, ParameterPlugin parameterPlugin,
- ValueNode[] arguments) {
+ int inliningDepth, LoopExplosionPlugin loopExplosionPlugin, ValueNode[] arguments) {
super(callerLoopScope, targetGraph, encodedGraph, loopExplosionKind(method, loopExplosionPlugin));
this.caller = caller;
this.method = method;
this.invokeData = invokeData;
this.inliningDepth = inliningDepth;
- this.loopExplosionPlugin = loopExplosionPlugin;
- this.invocationPlugins = invocationPlugins;
- this.inlineInvokePlugins = inlineInvokePlugins;
- this.parameterPlugin = parameterPlugin;
this.arguments = arguments;
}
+ @Override
public boolean isInlinedMethod() {
return caller != null;
}
@@ -219,7 +210,7 @@
@Override
public StructuredGraph getGraph() {
- return methodScope.graph;
+ return graph;
}
@Override
@@ -399,10 +390,19 @@
}
protected final OptionValues options;
+ private final LoopExplosionPlugin loopExplosionPlugin;
+ private final InvocationPlugins invocationPlugins;
+ private final InlineInvokePlugin[] inlineInvokePlugins;
+ private final ParameterPlugin parameterPlugin;
- public PEGraphDecoder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, StampProvider stampProvider,
- Architecture architecture, OptionValues options) {
- super(metaAccess, constantReflection, constantFieldProvider, stampProvider, true, architecture);
+ public PEGraphDecoder(Architecture architecture, StructuredGraph graph, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider,
+ StampProvider stampProvider, OptionValues options, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin[] inlineInvokePlugins,
+ ParameterPlugin parameterPlugin) {
+ super(architecture, graph, metaAccess, constantReflection, constantFieldProvider, stampProvider, true);
+ this.loopExplosionPlugin = loopExplosionPlugin;
+ this.invocationPlugins = invocationPlugins;
+ this.inlineInvokePlugins = inlineInvokePlugins;
+ this.parameterPlugin = parameterPlugin;
this.options = options;
}
@@ -414,20 +414,17 @@
}
}
- public void decode(StructuredGraph targetGraph, ResolvedJavaMethod method, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin[] inlineInvokePlugins,
- ParameterPlugin parameterPlugin) {
- PEMethodScope methodScope = new PEMethodScope(targetGraph, null, null, lookupEncodedGraph(method, null), method, null, 0, loopExplosionPlugin, invocationPlugins,
- inlineInvokePlugins,
- parameterPlugin, null);
+ public void decode(ResolvedJavaMethod method) {
+ PEMethodScope methodScope = new PEMethodScope(graph, null, null, lookupEncodedGraph(method, null), method, null, 0, loopExplosionPlugin, null);
decode(createInitialLoopScope(methodScope, null));
cleanupGraph(methodScope);
- Debug.dump(Debug.VERBOSE_LOG_LEVEL, methodScope.graph, "After graph cleanup");
- assert methodScope.graph.verify();
+ Debug.dump(Debug.VERBOSE_LEVEL, graph, "After graph cleanup");
+ assert graph.verify();
try {
/* Check that the control flow graph can be computed, to catch problems early. */
- assert CFGVerifier.verify(ControlFlowGraph.compute(methodScope.graph, true, true, true, true));
+ assert CFGVerifier.verify(ControlFlowGraph.compute(graph, true, true, true, true));
} catch (Throwable ex) {
throw GraalError.shouldNotReachHere("Control flow graph not valid after partial evaluation");
}
@@ -437,7 +434,7 @@
protected void cleanupGraph(MethodScope methodScope) {
super.cleanupGraph(methodScope);
- for (FrameState frameState : methodScope.graph.getNodes(FrameState.TYPE)) {
+ for (FrameState frameState : graph.getNodes(FrameState.TYPE)) {
if (frameState.bci == BytecodeFrame.UNWIND_BCI) {
/*
* handleMissingAfterExceptionFrameState is called during graph decoding from
@@ -492,7 +489,7 @@
}
/* We know that we need an invoke, so now we can add the call target to the graph. */
- methodScope.graph.add(callTarget);
+ graph.add(callTarget);
registerNode(loopScope, invokeData.callTargetOrderId, callTarget, false, false);
return super.handleInvoke(methodScope, loopScope, invokeData);
}
@@ -519,21 +516,21 @@
return inlineLoopScope;
}
- for (InlineInvokePlugin plugin : methodScope.inlineInvokePlugins) {
+ for (InlineInvokePlugin plugin : inlineInvokePlugins) {
plugin.notifyNotInlined(new PENonAppendGraphBuilderContext(methodScope, invokeData.invoke), callTarget.targetMethod(), invokeData.invoke);
}
return null;
}
protected boolean tryInvocationPlugin(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) {
- if (methodScope.invocationPlugins == null) {
+ if (invocationPlugins == null) {
return false;
}
Invoke invoke = invokeData.invoke;
ResolvedJavaMethod targetMethod = callTarget.targetMethod();
- InvocationPlugin invocationPlugin = methodScope.invocationPlugins.lookupInvocation(targetMethod);
+ InvocationPlugin invocationPlugin = invocationPlugins.lookupInvocation(targetMethod);
if (invocationPlugin == null) {
return false;
}
@@ -546,8 +543,7 @@
*/
invoke.asNode().replaceAtPredecessor(null);
- PEMethodScope inlineScope = new PEMethodScope(methodScope.graph, methodScope, loopScope, null, targetMethod, invokeData, methodScope.inliningDepth + 1, methodScope.loopExplosionPlugin,
- methodScope.invocationPlugins, methodScope.inlineInvokePlugins, null, arguments);
+ PEMethodScope inlineScope = new PEMethodScope(graph, methodScope, loopScope, null, targetMethod, invokeData, methodScope.inliningDepth + 1, loopExplosionPlugin, arguments);
PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(inlineScope, invokePredecessor);
InvocationPluginReceiver invocationPluginReceiver = new InvocationPluginReceiver(graphBuilderContext);
@@ -587,7 +583,7 @@
ValueNode[] arguments = callTarget.arguments().toArray(new ValueNode[0]);
GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope, invokeData.invoke);
- for (InlineInvokePlugin plugin : methodScope.inlineInvokePlugins) {
+ for (InlineInvokePlugin plugin : inlineInvokePlugins) {
InlineInfo inlineInfo = plugin.shouldInlineInvoke(graphBuilderContext, targetMethod, arguments);
if (inlineInfo != null) {
if (inlineInfo.getMethodToInline() == null) {
@@ -611,7 +607,7 @@
throw tooDeepInlining(methodScope);
}
- for (InlineInvokePlugin plugin : methodScope.inlineInvokePlugins) {
+ for (InlineInvokePlugin plugin : inlineInvokePlugins) {
plugin.notifyBeforeInline(inlineMethod);
}
@@ -620,16 +616,8 @@
FixedWithNextNode predecessor = (FixedWithNextNode) invokeNode.predecessor();
invokeNode.replaceAtPredecessor(null);
- PEMethodScope inlineScope = new PEMethodScope(methodScope.graph, methodScope, loopScope, graphToInline, inlineMethod, invokeData, methodScope.inliningDepth + 1,
- methodScope.loopExplosionPlugin, methodScope.invocationPlugins, methodScope.inlineInvokePlugins, null, arguments);
-
- /*
- * After decoding all the nodes of the inlined method, we need to re-wire the return and
- * unwind nodes. Since inlining is non-recursive, this cannot be done at the end of this
- * method, but must be registered as a cleanup task that runs when all nodes of the inlined
- * methods have been decoded.
- */
- inlineScope.cleanupTasks.add(() -> finishInlining(methodScope, loopScope, invokeData, inlineMethod, inlineScope));
+ PEMethodScope inlineScope = new PEMethodScope(graph, methodScope, loopScope, graphToInline, inlineMethod, invokeData, methodScope.inliningDepth + 1,
+ loopExplosionPlugin, arguments);
/*
* Do the actual inlining by returning the initial loop scope for the inlined method scope.
@@ -637,32 +625,43 @@
return createInitialLoopScope(inlineScope, predecessor);
}
- protected void finishInlining(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, ResolvedJavaMethod inlineMethod, PEMethodScope inlineScope) {
+ @Override
+ protected void finishInlining(MethodScope is) {
+ PEMethodScope inlineScope = (PEMethodScope) is;
+ ResolvedJavaMethod inlineMethod = inlineScope.method;
+ PEMethodScope methodScope = inlineScope.caller;
+ LoopScope loopScope = inlineScope.callerLoopScope;
+ InvokeData invokeData = inlineScope.invokeData;
Invoke invoke = invokeData.invoke;
FixedNode invokeNode = invoke.asNode();
ValueNode exceptionValue = null;
- List<UnwindNode> unwindNodes = inlineScope.unwindNodes;
- Iterator<UnwindNode> iter = unwindNodes.iterator();
- while (iter.hasNext()) {
- if (iter.next().isDeleted()) {
- iter.remove();
+ int returnNodeCount = 0;
+ int unwindNodeCount = 0;
+ List<ControlSinkNode> returnAndUnwindNodes = inlineScope.returnAndUnwindNodes;
+ for (int i = 0; i < returnAndUnwindNodes.size(); i++) {
+ FixedNode fixedNode = returnAndUnwindNodes.get(i);
+ if (fixedNode instanceof ReturnNode) {
+ returnNodeCount++;
+ } else if (fixedNode.isAlive()) {
+ assert fixedNode instanceof UnwindNode;
+ unwindNodeCount++;
}
}
- if (!unwindNodes.isEmpty()) {
+ if (unwindNodeCount > 0) {
FixedNode unwindReplacement;
if (invoke instanceof InvokeWithExceptionNode) {
/* Decoding continues for the exception handler. */
unwindReplacement = makeStubNode(methodScope, loopScope, invokeData.exceptionNextOrderId);
} else {
/* No exception handler available, so the only thing we can do is deoptimize. */
- unwindReplacement = methodScope.graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
+ unwindReplacement = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
}
- if (unwindNodes.size() == 1) {
+ if (unwindNodeCount == 1) {
/* Only one UnwindNode, we can use the exception directly. */
- UnwindNode unwindNode = unwindNodes.get(0);
+ UnwindNode unwindNode = getSingleMatchingNode(returnAndUnwindNodes, returnNodeCount > 0, UnwindNode.class);
exceptionValue = unwindNode.exception();
unwindNode.replaceAndDelete(unwindReplacement);
@@ -673,8 +672,9 @@
* also explode exception paths. Merge the exception in a similar way as multiple
* return values.
*/
- MergeNode unwindMergeNode = methodScope.graph.add(new MergeNode());
- exceptionValue = InliningUtil.mergeValueProducers(unwindMergeNode, unwindNodes, unwindNode -> unwindNode.exception());
+ MergeNode unwindMergeNode = graph.add(new MergeNode());
+ exceptionValue = InliningUtil.mergeValueProducers(unwindMergeNode, getMatchingNodes(returnAndUnwindNodes, returnNodeCount > 0, UnwindNode.class, unwindNodeCount),
+ unwindNode -> unwindNode.exception());
unwindMergeNode.setNext(unwindReplacement);
ensureExceptionStateDecoded(inlineScope);
@@ -686,22 +686,19 @@
assert !(invoke instanceof InvokeWithExceptionNode) || ((InvokeWithExceptionNode) invoke).exceptionEdge() == null;
ValueNode returnValue;
- List<ReturnNode> returnNodes = inlineScope.returnNodes;
- if (!returnNodes.isEmpty()) {
- if (returnNodes.size() == 1) {
- ReturnNode returnNode = returnNodes.get(0);
- returnValue = returnNode.result();
- FixedNode n = nodeAfterInvoke(methodScope, loopScope, invokeData, AbstractBeginNode.prevBegin(returnNode));
- returnNode.replaceAndDelete(n);
- } else {
- AbstractMergeNode merge = methodScope.graph.add(new MergeNode());
- merge.setStateAfter((FrameState) ensureNodeCreated(methodScope, loopScope, invokeData.stateAfterOrderId));
- returnValue = InliningUtil.mergeReturns(merge, returnNodes);
- FixedNode n = nodeAfterInvoke(methodScope, loopScope, invokeData, merge);
- merge.setNext(n);
- }
+ if (returnNodeCount == 0) {
+ returnValue = null;
+ } else if (returnNodeCount == 1) {
+ ReturnNode returnNode = getSingleMatchingNode(returnAndUnwindNodes, unwindNodeCount > 0, ReturnNode.class);
+ returnValue = returnNode.result();
+ FixedNode n = nodeAfterInvoke(methodScope, loopScope, invokeData, AbstractBeginNode.prevBegin(returnNode));
+ returnNode.replaceAndDelete(n);
} else {
- returnValue = null;
+ AbstractMergeNode merge = graph.add(new MergeNode());
+ merge.setStateAfter((FrameState) ensureNodeCreated(methodScope, loopScope, invokeData.stateAfterOrderId));
+ returnValue = InliningUtil.mergeReturns(merge, getMatchingNodes(returnAndUnwindNodes, unwindNodeCount > 0, ReturnNode.class, returnNodeCount));
+ FixedNode n = nodeAfterInvoke(methodScope, loopScope, invokeData, merge);
+ merge.setNext(n);
}
invokeNode.replaceAtUsages(returnValue);
@@ -718,13 +715,42 @@
}
deleteInvoke(invoke);
- for (InlineInvokePlugin plugin : methodScope.inlineInvokePlugins) {
+ for (InlineInvokePlugin plugin : inlineInvokePlugins) {
plugin.notifyAfterInline(inlineMethod);
}
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> T getSingleMatchingNode(List<ControlSinkNode> returnAndUnwindNodes, boolean hasNonMatchingEntries, Class<T> clazz) {
+ if (!hasNonMatchingEntries) {
+ assert returnAndUnwindNodes.size() == 1;
+ return (T) returnAndUnwindNodes.get(0);
+ }
- if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL) && DumpDuringGraphBuilding.getValue(options)) {
- Debug.dump(Debug.INFO_LOG_LEVEL, methodScope.graph, "Inline finished: %s.%s", inlineMethod.getDeclaringClass().getUnqualifiedName(), inlineMethod.getName());
+ for (int i = 0; i < returnAndUnwindNodes.size(); i++) {
+ ControlSinkNode node = returnAndUnwindNodes.get(i);
+ if (clazz.isInstance(node)) {
+ return (T) node;
+ }
}
+ throw GraalError.shouldNotReachHere();
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> List<T> getMatchingNodes(List<ControlSinkNode> returnAndUnwindNodes, boolean hasNonMatchingEntries, Class<T> clazz, int resultCount) {
+ if (!hasNonMatchingEntries) {
+ return (List<T>) returnAndUnwindNodes;
+ }
+
+ List<T> result = new ArrayList<>(resultCount);
+ for (int i = 0; i < returnAndUnwindNodes.size(); i++) {
+ ControlSinkNode node = returnAndUnwindNodes.get(i);
+ if (clazz.isInstance(node)) {
+ result.add((T) node);
+ }
+ }
+ assert result.size() == resultCount;
+ return result;
}
private static RuntimeException tooDeepInlining(PEMethodScope methodScope) {
@@ -809,25 +835,27 @@
}
@Override
- protected Node handleFloatingNodeBeforeAdd(MethodScope s, LoopScope loopScope, Node node) {
+ protected Node handleFloatingNodeBeforeAdd(MethodScope s, LoopScope loopScope, Node n) {
PEMethodScope methodScope = (PEMethodScope) s;
+ Node node = n;
if (node instanceof ParameterNode) {
ParameterNode param = (ParameterNode) node;
- if (methodScope.arguments != null) {
+ if (methodScope.isInlinedMethod()) {
Node result = methodScope.arguments[param.index()];
assert result != null;
return result;
- } else if (methodScope.parameterPlugin != null) {
+ } else if (parameterPlugin != null) {
+ assert !methodScope.isInlinedMethod();
GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope, null);
- Node result = methodScope.parameterPlugin.interceptParameter(graphBuilderContext, param.index(),
+ Node result = parameterPlugin.interceptParameter(graphBuilderContext, param.index(),
StampPair.create(param.stamp(), param.uncheckedStamp()));
if (result != null) {
return result;
}
}
-
+ node = param.copyWithInputs();
}
return super.handleFloatingNodeBeforeAdd(methodScope, loopScope, node);
@@ -841,7 +869,7 @@
}
JavaKind invokeReturnKind = methodScope.invokeData.invoke.asNode().getStackKind();
- FrameState outerState = stateAtReturn.duplicateModified(methodScope.graph, methodScope.invokeData.invoke.bci(), stateAtReturn.rethrowException(), true, invokeReturnKind, null, null);
+ FrameState outerState = stateAtReturn.duplicateModified(graph, methodScope.invokeData.invoke.bci(), stateAtReturn.rethrowException(), true, invokeReturnKind, null, null);
/*
* When the encoded graph has methods inlining, we can already have a proper caller
@@ -866,7 +894,7 @@
ensureStateAfterDecoded(methodScope);
assert methodScope.exceptionPlaceholderNode == null;
- methodScope.exceptionPlaceholderNode = methodScope.graph.add(new ExceptionPlaceholderNode());
+ methodScope.exceptionPlaceholderNode = graph.add(new ExceptionPlaceholderNode());
registerNode(methodScope.callerLoopScope, methodScope.invokeData.exceptionOrderId, methodScope.exceptionPlaceholderNode, false, false);
FrameState exceptionState = (FrameState) ensureNodeCreated(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.exceptionStateOrderId);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java Thu Apr 06 23:01:27 2017 +0000
@@ -322,7 +322,7 @@
finalizeGraph(graph);
- Debug.dump(Debug.INFO_LOG_LEVEL, graph, "%s: Final", method.getName());
+ Debug.dump(Debug.INFO_LEVEL, graph, "%s: Final", method.getName());
return graph;
} catch (Throwable e) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Thu Apr 06 23:01:27 2017 +0000
@@ -25,6 +25,7 @@
import static java.util.FormattableFlags.ALTERNATE;
import static org.graalvm.compiler.core.common.LocationIdentity.any;
import static org.graalvm.compiler.debug.Debug.applyFormattingFlagsAndWidth;
+import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugStubsAndSnippets;
import static org.graalvm.compiler.graph.iterators.NodePredicates.isNotA;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED;
@@ -57,7 +58,9 @@
import org.graalvm.compiler.core.common.type.TypeReference;
import org.graalvm.compiler.debug.Debug;
import org.graalvm.compiler.debug.Debug.Scope;
+import org.graalvm.compiler.debug.internal.DebugScope;
import org.graalvm.compiler.debug.DebugCloseable;
+import org.graalvm.compiler.debug.DebugConfig;
import org.graalvm.compiler.debug.DebugCounter;
import org.graalvm.compiler.debug.DebugTimer;
import org.graalvm.compiler.debug.GraalError;
@@ -82,8 +85,8 @@
import org.graalvm.compiler.nodes.MergeNode;
import org.graalvm.compiler.nodes.ParameterNode;
import org.graalvm.compiler.nodes.PhiNode;
-import org.graalvm.compiler.nodes.PiNode;
import org.graalvm.compiler.nodes.PiNode.Placeholder;
+import org.graalvm.compiler.nodes.PiNode.PlaceholderStamp;
import org.graalvm.compiler.nodes.ReturnNode;
import org.graalvm.compiler.nodes.StartNode;
import org.graalvm.compiler.nodes.StateSplit;
@@ -632,7 +635,8 @@
SnippetTemplate template = Options.UseSnippetTemplateCache.getValue(options) && args.cacheable ? templates.get(args.cacheKey) : null;
if (template == null) {
SnippetTemplates.increment();
- try (DebugCloseable a = SnippetTemplateCreationTime.start(); Scope s = Debug.scope("SnippetSpecialization", args.info.method)) {
+ DebugConfig config = DebugStubsAndSnippets.getValue(options) ? DebugScope.getConfig() : Debug.silentConfig();
+ try (DebugCloseable a = SnippetTemplateCreationTime.start(); Scope s = Debug.sandbox("SnippetSpecialization", config, args.info.method)) {
template = new SnippetTemplate(options, providers, snippetReflection, args);
if (Options.UseSnippetTemplateCache.getValue(options) && args.cacheable) {
templates.put(args.cacheKey, template);
@@ -744,7 +748,7 @@
}
snippetCopy.addDuplicates(snippetGraph.getNodes(), snippetGraph, snippetGraph.getNodeCount(), nodeReplacements);
- Debug.dump(Debug.INFO_LOG_LEVEL, snippetCopy, "Before specialization");
+ Debug.dump(Debug.INFO_LEVEL, snippetCopy, "Before specialization");
// Gather the template parameters
parameters = new Object[parameterCount];
@@ -772,10 +776,10 @@
for (Node usage : placeholder.usages().snapshot()) {
if (usage instanceof LoadIndexedNode) {
LoadIndexedNode loadIndexed = (LoadIndexedNode) usage;
- Debug.dump(Debug.INFO_LOG_LEVEL, snippetCopy, "Before replacing %s", loadIndexed);
+ Debug.dump(Debug.INFO_LEVEL, snippetCopy, "Before replacing %s", loadIndexed);
LoadSnippetVarargParameterNode loadSnippetParameter = snippetCopy.add(new LoadSnippetVarargParameterNode(params, loadIndexed.index(), loadIndexed.stamp()));
snippetCopy.replaceFixedWithFixed(loadIndexed, loadSnippetParameter);
- Debug.dump(Debug.INFO_LOG_LEVEL, snippetCopy, "After replacing %s", loadIndexed);
+ Debug.dump(Debug.INFO_LEVEL, snippetCopy, "After replacing %s", loadIndexed);
} else if (usage instanceof StoreIndexedNode) {
/*
* The template lowering doesn't really treat this as an array so
@@ -813,11 +817,15 @@
ArrayList<StateSplit> curSideEffectNodes = new ArrayList<>();
ArrayList<DeoptimizingNode> curDeoptNodes = new ArrayList<>();
- ArrayList<ValueNode> curStampNodes = new ArrayList<>();
+ ArrayList<ValueNode> curPlaceholderStampedNodes = new ArrayList<>();
for (Node node : snippetCopy.getNodes()) {
- if (node instanceof ValueNode && ((ValueNode) node).stamp() == StampFactory.forNodeIntrinsic()) {
- curStampNodes.add((ValueNode) node);
+ if (node instanceof ValueNode) {
+ ValueNode valueNode = (ValueNode) node;
+ if (valueNode.stamp() == PlaceholderStamp.singleton()) {
+ curPlaceholderStampedNodes.add(valueNode);
+ }
}
+
if (node instanceof StateSplit) {
StateSplit stateSplit = (StateSplit) node;
FrameState frameState = stateSplit.stateAfter();
@@ -889,7 +897,7 @@
this.memoryAnchor = null;
}
}
- Debug.dump(Debug.INFO_LOG_LEVEL, snippet, "SnippetTemplate after fixing memory anchoring");
+ Debug.dump(Debug.INFO_LEVEL, snippet, "SnippetTemplate after fixing memory anchoring");
List<ReturnNode> returnNodes = snippet.getNodes(ReturnNode.TYPE).snapshot();
if (returnNodes.isEmpty()) {
@@ -924,7 +932,7 @@
this.sideEffectNodes = curSideEffectNodes;
this.deoptNodes = curDeoptNodes;
- this.stampNodes = curStampNodes;
+ this.placeholderStampedNodes = curPlaceholderStampedNodes;
nodes = new ArrayList<>(snippet.getNodeCount());
for (Node node : snippet.getNodes()) {
@@ -934,7 +942,7 @@
}
Debug.counter("SnippetTemplateNodeCount[%#s]", args).add(nodes.size());
- Debug.dump(Debug.INFO_LOG_LEVEL, snippet, "SnippetTemplate final state");
+ Debug.dump(Debug.INFO_LEVEL, snippet, "SnippetTemplate final state");
} catch (Throwable ex) {
throw Debug.handle(ex);
@@ -1043,9 +1051,9 @@
private final ArrayList<DeoptimizingNode> deoptNodes;
/**
- * The nodes that inherit the {@link ValueNode#stamp()} from the replacee during instantiation.
+ * Nodes that have a stamp originating from a {@link Placeholder}.
*/
- private final ArrayList<ValueNode> stampNodes;
+ private final ArrayList<ValueNode> placeholderStampedNodes;
/**
* The nodes to be inlined when this specialization is instantiated.
@@ -1364,6 +1372,21 @@
*/
@SuppressWarnings("try")
public UnmodifiableEconomicMap<Node, Node> instantiate(MetaAccessProvider metaAccess, FixedNode replacee, UsageReplacer replacer, Arguments args) {
+ return instantiate(metaAccess, replacee, replacer, args, true);
+ }
+
+ /**
+ * Replaces a given fixed node with this specialized snippet.
+ *
+ * @param metaAccess
+ * @param replacee the node that will be replaced
+ * @param replacer object that replaces the usages of {@code replacee}
+ * @param args the arguments to be bound to the flattened positional parameters of the snippet
+ * @param killReplacee is true, the replacee node is deleted
+ * @return the map of duplicated nodes (original -> duplicate)
+ */
+ @SuppressWarnings("try")
+ public UnmodifiableEconomicMap<Node, Node> instantiate(MetaAccessProvider metaAccess, FixedNode replacee, UsageReplacer replacer, Arguments args, boolean killReplacee) {
assert assertSnippetKills(replacee);
try (DebugCloseable a = args.info.instantiationTimer.start(); DebugCloseable b = instantiationTimer.start()) {
args.info.instantiationCounter.increment();
@@ -1375,7 +1398,7 @@
EconomicMap<Node, Node> replacements = bind(replaceeGraph, metaAccess, args);
replacements.put(entryPointNode, AbstractBeginNode.prevBegin(replacee));
UnmodifiableEconomicMap<Node, Node> duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacements);
- Debug.dump(Debug.INFO_LOG_LEVEL, replaceeGraph, "After inlining snippet %s", snippet.method());
+ Debug.dump(Debug.DETAILED_LEVEL, replaceeGraph, "After inlining snippet %s", snippet.method());
// Re-wire the control flow graph around the replacee
FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
@@ -1458,10 +1481,12 @@
}
}
- // Remove the replacee from its graph
- GraphUtil.killCFG(replacee);
+ if (killReplacee) {
+ // Remove the replacee from its graph
+ GraphUtil.killCFG(replacee);
+ }
- Debug.dump(Debug.INFO_LOG_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this);
+ Debug.dump(Debug.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this);
return duplicates;
}
}
@@ -1478,14 +1503,14 @@
}
private void updateStamps(ValueNode replacee, UnmodifiableEconomicMap<Node, Node> duplicates) {
- for (ValueNode stampNode : stampNodes) {
- Node stampDup = duplicates.get(stampNode);
- if (stampDup instanceof PiNode.Placeholder) {
- PiNode.Placeholder placeholder = (Placeholder) stampDup;
- PiNode pi = placeholder.getReplacement(replacee.stamp());
- placeholder.replaceAndDelete(pi);
+ for (ValueNode node : placeholderStampedNodes) {
+ ValueNode dup = (ValueNode) duplicates.get(node);
+ Stamp replaceeStamp = replacee.stamp();
+ if (node instanceof Placeholder) {
+ Placeholder placeholderDup = (Placeholder) dup;
+ placeholderDup.makeReplacement(replaceeStamp);
} else {
- ((ValueNode) stampDup).setStamp(replacee.stamp());
+ dup.setStamp(replaceeStamp);
}
}
for (ParameterNode paramNode : snippet.getNodes(ParameterNode.TYPE)) {
@@ -1526,7 +1551,7 @@
EconomicMap<Node, Node> replacements = bind(replaceeGraph, metaAccess, args);
replacements.put(entryPointNode, tool.getCurrentGuardAnchor().asNode());
UnmodifiableEconomicMap<Node, Node> duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacements);
- Debug.dump(Debug.INFO_LOG_LEVEL, replaceeGraph, "After inlining snippet %s", snippet.method());
+ Debug.dump(Debug.DETAILED_LEVEL, replaceeGraph, "After inlining snippet %s", snippet.method());
FixedWithNextNode lastFixedNode = tool.lastFixedNode();
assert lastFixedNode != null && lastFixedNode.isAlive() : replaceeGraph + " lastFixed=" + lastFixedNode;
@@ -1550,7 +1575,7 @@
returnDuplicate.replaceAndDelete(next);
}
- Debug.dump(Debug.INFO_LOG_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this);
+ Debug.dump(Debug.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this);
}
}
@@ -1588,7 +1613,7 @@
}
}
UnmodifiableEconomicMap<Node, Node> duplicates = replaceeGraph.addDuplicates(floatingNodes, snippet, floatingNodes.size(), replacements);
- Debug.dump(Debug.INFO_LOG_LEVEL, replaceeGraph, "After inlining snippet %s", snippet.method());
+ Debug.dump(Debug.DETAILED_LEVEL, replaceeGraph, "After inlining snippet %s", snippet.method());
rewireFrameStates(replacee, duplicates);
updateStamps(replacee, duplicates);
@@ -1600,7 +1625,7 @@
ValueNode returnValue = (ValueNode) duplicates.get(returnNode.result());
replacer.replace(replacee, returnValue);
- Debug.dump(Debug.INFO_LOG_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this);
+ Debug.dump(Debug.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this);
}
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Thu Apr 06 23:01:27 2017 +0000
@@ -42,6 +42,7 @@
import org.graalvm.compiler.core.common.LocationIdentity;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.calc.UnsignedMath;
+import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
@@ -76,23 +77,23 @@
import org.graalvm.compiler.nodes.extended.BranchProbabilityNode;
import org.graalvm.compiler.nodes.extended.GetClassNode;
import org.graalvm.compiler.nodes.extended.MembarNode;
+import org.graalvm.compiler.nodes.extended.RawLoadNode;
+import org.graalvm.compiler.nodes.extended.RawStoreNode;
import org.graalvm.compiler.nodes.extended.UnboxNode;
-import org.graalvm.compiler.nodes.extended.RawLoadNode;
import org.graalvm.compiler.nodes.extended.UnsafeMemoryLoadNode;
import org.graalvm.compiler.nodes.extended.UnsafeMemoryStoreNode;
-import org.graalvm.compiler.nodes.extended.RawStoreNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
import org.graalvm.compiler.nodes.java.ClassIsAssignableFromNode;
-import org.graalvm.compiler.nodes.java.UnsafeCompareAndSwapNode;
import org.graalvm.compiler.nodes.java.DynamicNewArrayNode;
import org.graalvm.compiler.nodes.java.DynamicNewInstanceNode;
import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode;
import org.graalvm.compiler.nodes.java.LoadFieldNode;
import org.graalvm.compiler.nodes.java.RegisterFinalizerNode;
+import org.graalvm.compiler.nodes.java.UnsafeCompareAndSwapNode;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.nodes.virtual.EnsureVirtualizedNode;
import org.graalvm.compiler.replacements.nodes.ReverseBytesNode;
@@ -173,7 +174,8 @@
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_VALUE_FIELD);
- b.addPush(JavaKind.Object, LoadFieldNode.create(b.getAssumptions(), value, field));
+ b.addPush(JavaKind.Object, LoadFieldNode.create(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(),
+ b.getOptions(), b.getAssumptions(), value, field, false, false));
return true;
}
});
@@ -557,8 +559,8 @@
r.register2("get" + c.getSimpleName() + "Unsafe", Node.class, long.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode node, ValueNode offset) {
- RawLoadNode value = b.add(new RawLoadNode(node, offset, JavaKind.Object, LocationIdentity.any()));
- value.setStamp(StampFactory.object(TypeReference.createTrusted(b.getAssumptions(), metaAccess.lookupJavaType(c))));
+ ObjectStamp stamp = StampFactory.object(TypeReference.createTrusted(b.getAssumptions(), metaAccess.lookupJavaType(c)));
+ RawLoadNode value = b.add(new RawLoadNode(stamp, node, offset, LocationIdentity.any(), JavaKind.Object));
b.addPush(JavaKind.Object, value);
return true;
}
@@ -881,8 +883,8 @@
if (totalCount == 0) {
b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter));
} else if (falseCount == 0 || trueCount == 0) {
- boolean expected = falseCount == 0 ? true : false;
- LogicNode condition = b.add(IntegerEqualsNode.create(result, b.add(ConstantNode.forBoolean(!expected)), /* constantReflection */ null));
+ boolean expected = falseCount == 0;
+ LogicNode condition = b.addWithInputs(IntegerEqualsNode.create(result, b.add(ConstantNode.forBoolean(!expected))));
b.append(new FixedGuardNode(condition, DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile, true));
newResult = b.add(ConstantNode.forBoolean(expected));
} else {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -204,10 +204,7 @@
return;
}
VirtualArrayNode srcVirtual = (VirtualArrayNode) srcAlias;
- if (destVirtual.componentType().getJavaKind() != JavaKind.Object) {
- return;
- }
- if (srcVirtual.componentType().getJavaKind() != JavaKind.Object) {
+ if (destVirtual.componentType().getJavaKind() != srcVirtual.componentType().getJavaKind()) {
return;
}
if (!checkBounds(srcPosInt, len, srcVirtual)) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -174,7 +174,7 @@
}
}
InliningUtil.inline(invoke, replacementGraph, false, targetMethod);
- Debug.dump(Debug.INFO_LOG_LEVEL, graph(), "After inlining replacement %s", replacementGraph);
+ Debug.dump(Debug.DETAILED_LEVEL, graph(), "After inlining replacement %s", replacementGraph);
} else {
if (isPlaceholderBci(invoke.bci())) {
throw new GraalError("%s: cannot lower to invoke with placeholder BCI: %s", graph(), this);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -335,8 +335,8 @@
adder.add(new ValueAnchorNode(newGuard));
guard = newGuard;
}
- PiNode piNode = adder.add(new PiNode(argument, StampFactory.object(targetType), guard.asNode()));
- arguments[index] = piNode;
+ ValueNode valueNode = adder.add(PiNode.create(argument, StampFactory.object(targetType), guard.asNode()));
+ arguments[index] = valueNode;
} else {
inst.safeDelete();
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReadRegisterNode.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReadRegisterNode.java Thu Apr 06 23:01:27 2017 +0000
@@ -26,6 +26,7 @@
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.NodeInfo;
@@ -71,8 +72,8 @@
this.incoming = incoming;
}
- public ReadRegisterNode(Register register, boolean directUse, boolean incoming) {
- super(TYPE, StampFactory.forNodeIntrinsic());
+ public ReadRegisterNode(@InjectedNodeParameter Stamp stamp, Register register, boolean directUse, boolean incoming) {
+ super(TYPE, stamp);
assert register != null;
this.register = register;
this.directUse = directUse;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider.processor/src/org/graalvm/compiler/serviceprovider/processor/ServiceProviderProcessor.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider.processor/src/org/graalvm/compiler/serviceprovider/processor/ServiceProviderProcessor.java Thu Apr 06 23:01:27 2017 +0000
@@ -25,7 +25,10 @@
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
@@ -53,6 +56,7 @@
public class ServiceProviderProcessor extends AbstractProcessor {
private final Set<TypeElement> processed = new HashSet<>();
+ private final Map<TypeElement, String> serviceProviders = new HashMap<>();
@Override
public SourceVersion getSupportedSourceVersion() {
@@ -82,23 +86,22 @@
} catch (MirroredTypeException ex) {
TypeMirror serviceInterface = ex.getTypeMirror();
if (verifyAnnotation(serviceInterface, serviceProvider)) {
- String interfaceName = ex.getTypeMirror().toString();
- createProviderFile(serviceProvider, interfaceName);
+ if (serviceProvider.getNestingKind().isNested()) {
+ /*
+ * This is a simplifying constraint that means we don't have to process the
+ * qualified name to insert '$' characters at the relevant positions.
+ */
+ String msg = String.format("Service provider class %s must be a top level class", serviceProvider.getSimpleName());
+ processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider);
+ } else {
+ serviceProviders.put(serviceProvider, ex.getTypeMirror().toString());
+ }
}
}
}
}
- private void createProviderFile(TypeElement serviceProvider, String interfaceName) {
- if (serviceProvider.getNestingKind().isNested()) {
- // This is a simplifying constraint that means we don't have to
- // processed the qualified name to insert '$' characters at
- // the relevant positions.
- String msg = String.format("Service provider class %s must be a top level class", serviceProvider.getSimpleName());
- processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider);
- return;
- }
-
+ private void writeProviderFile(TypeElement serviceProvider, String interfaceName) {
String filename = "META-INF/providers/" + serviceProvider.getQualifiedName();
try {
FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, serviceProvider);
@@ -114,7 +117,7 @@
* Determines if a given exception is (most likely) caused by
* <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599">Bug 367599</a>.
*/
- public static boolean isBug367599(Throwable t) {
+ private static boolean isBug367599(Throwable t) {
if (t instanceof FilerException) {
for (StackTraceElement ste : t.getStackTrace()) {
if (ste.toString().contains("org.eclipse.jdt.internal.apt.pluggable.core.filer.IdeFilerImpl.create")) {
@@ -123,15 +126,16 @@
}
}
}
- if (t.getCause() != null) {
- return isBug367599(t.getCause());
- }
- return false;
+ return t.getCause() != null && isBug367599(t.getCause());
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) {
+ for (Entry<TypeElement, String> e : serviceProviders.entrySet()) {
+ writeProviderFile(e.getKey(), e.getValue());
+ }
+ serviceProviders.clear();
return true;
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java Thu Apr 06 23:01:27 2017 +0000
@@ -124,8 +124,6 @@
Class<?> expectedClass = expected.getClass();
Class<?> actualClass = actual.getClass();
if (expectedClass.isArray()) {
- Assert.assertTrue(message, expected != null);
- Assert.assertTrue(message, actual != null);
Assert.assertEquals(message, expectedClass, actual.getClass());
if (expected instanceof int[]) {
Assert.assertArrayEquals(message, (int[]) expected, (int[]) actual);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java Thu Apr 06 23:01:27 2017 +0000
@@ -25,8 +25,13 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Formatter;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.graalvm.util.CollectionsUtil;
/**
* Utility methods for spawning a VM in a subprocess during unit tests.
@@ -54,6 +59,63 @@
}
/**
+ * Pattern for a single shell command argument that does not need to quoted.
+ */
+ private static final Pattern SAFE_SHELL_ARG = Pattern.compile("[A-Za-z0-9@%_\\-\\+=:,\\./]+");
+
+ /**
+ * Reliably quote a string as a single shell command argument.
+ */
+ public static String quoteShellArg(String arg) {
+ if (arg.isEmpty()) {
+ return "\"\"";
+ }
+ Matcher m = SAFE_SHELL_ARG.matcher(arg);
+ if (m.matches()) {
+ return arg;
+ }
+ // See http://stackoverflow.com/a/1250279
+ return "'" + arg.replace("'", "'\"'\"'") + "'";
+ }
+
+ /**
+ * Formats an executed shell command followed by its output. The command is formatted such that
+ * it can be copy and pasted into a console for re-execution.
+ *
+ * @param command the list containing the program and its arguments
+ * @param outputLines the output of the command broken into lines
+ * @param header if non null, the returned string has a prefix of this value plus a newline
+ * @param trailer if non null, the returned string has a suffix of this value plus a newline
+ */
+ public static String formatExecutedCommand(List<String> command, List<String> outputLines, String header, String trailer) {
+ Formatter msg = new Formatter();
+ if (header != null) {
+ msg.format("%s%n", header);
+ }
+ msg.format("%s%n", CollectionsUtil.mapAndJoin(command, e -> quoteShellArg(String.valueOf(e)), " "));
+ for (String line : outputLines) {
+ msg.format("%s%n", line);
+ }
+ if (trailer != null) {
+ msg.format("%s%n", trailer);
+ }
+ return msg.toString();
+ }
+
+ /**
+ * Returns a new copy {@code args} with debugger arguments removed.
+ */
+ public static List<String> withoutDebuggerArguments(List<String> args) {
+ List<String> result = new ArrayList<>(args.size());
+ for (String arg : args) {
+ if (!(arg.equals("-Xdebug") || arg.startsWith("-Xrunjdwp:"))) {
+ result.add(arg);
+ }
+ }
+ return result;
+ }
+
+ /**
* Gets the command line used to start the current Java VM, including all VM arguments, but not
* including the main class or any Java arguments. This can be used to spawn an identical VM,
* but running different Java code.
@@ -68,9 +130,28 @@
}
}
- public static final List<String> JVM_OPTIONS_WITH_ONE_ARG = System.getProperty("java.specification.version").compareTo("1.9") < 0 ? //
- Arrays.asList("-cp", "-classpath") : //
- Arrays.asList("-cp", "-classpath", "-mp", "-modulepath", "-upgrademodulepath", "-addmods", "-m", "-limitmods");
+ private static final boolean isJava8OrEarlier = System.getProperty("java.specification.version").compareTo("1.9") < 0;
+
+ private static boolean hasArg(String optionName) {
+ if (optionName.equals("-cp") || optionName.equals("-classpath")) {
+ return true;
+ }
+ if (!isJava8OrEarlier) {
+ if (optionName.equals("--version") ||
+ optionName.equals("--show-version") ||
+ optionName.equals("--dry-run") ||
+ optionName.equals("--disable-@files") ||
+ optionName.equals("--dry-run") ||
+ optionName.equals("--help") ||
+ optionName.equals("--help-extra")) {
+ return false;
+ }
+ if (optionName.startsWith("--")) {
+ return optionName.indexOf('=') == -1;
+ }
+ }
+ return false;
+ }
private static int findMainClassIndex(List<String> commandLine) {
int i = 1; // Skip the java executable
@@ -79,7 +160,7 @@
String s = commandLine.get(i);
if (s.charAt(0) != '-') {
return i;
- } else if (JVM_OPTIONS_WITH_ONE_ARG.contains(s)) {
+ } else if (hasArg(s)) {
i += 2;
} else {
i++;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java Thu Apr 06 23:01:27 2017 +0000
@@ -194,7 +194,7 @@
Debug.log(" ==== cfg kill effects");
effects.apply(graph, obsoleteNodes, true);
}
- Debug.dump(Debug.VERBOSE_LOG_LEVEL, graph, "After applying effects");
+ Debug.dump(Debug.DETAILED_LEVEL, graph, "After applying effects");
assert VirtualUtil.assertNonReachable(graph, obsoleteNodes);
for (Node node : obsoleteNodes) {
if (node.isAlive() && node.hasNoUsages()) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java Thu Apr 06 23:01:27 2017 +0000
@@ -100,8 +100,8 @@
closure.applyEffects();
}
- if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) {
- Debug.dump(Debug.INFO_LOG_LEVEL, graph, "%s iteration", getName());
+ if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) {
+ Debug.dump(Debug.DETAILED_LEVEL, graph, "%s iteration", getName());
}
new DeadCodeEliminationPhase(Required).apply(graph);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeBlockState.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeBlockState.java Thu Apr 06 23:01:27 2017 +0000
@@ -118,6 +118,7 @@
private ObjectState[] getObjectStateArrayForModification() {
if (arrayRefCount.refCount > 1) {
objectStates = objectStates.clone();
+ arrayRefCount.refCount--;
arrayRefCount = new RefCount();
}
return objectStates;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java Thu Apr 06 23:01:27 2017 +0000
@@ -23,7 +23,7 @@
package org.graalvm.compiler.virtual.phases.ea;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.BitSet;
import java.util.Iterator;
import java.util.List;
import java.util.function.IntFunction;
@@ -432,15 +432,16 @@
counter.increment();
VirtualObjectNode virtual = virtualObjects.get(object);
state.materializeBefore(materializeBefore, virtual, effects);
- updateStatesForMaterialized(state, virtual, state.getObjectState(object).getMaterializedValue());
+ assert !updateStatesForMaterialized(state, virtual, state.getObjectState(object).getMaterializedValue()) : "method must already have been called before";
return true;
} else {
return false;
}
}
- public static void updateStatesForMaterialized(PartialEscapeBlockState<?> state, VirtualObjectNode virtual, ValueNode materializedValue) {
+ public static boolean updateStatesForMaterialized(PartialEscapeBlockState<?> state, VirtualObjectNode virtual, ValueNode materializedValue) {
// update all existing states with the newly materialized object
+ boolean change = false;
for (int i = 0; i < state.getStateCount(); i++) {
ObjectState objState = state.getObjectStateOptional(i);
if (objState != null && objState.isVirtual()) {
@@ -448,10 +449,12 @@
for (int i2 = 0; i2 < entries.length; i2++) {
if (entries[i2] == virtual) {
state.setEntry(i, i2, materializedValue);
+ change = true;
}
}
}
}
+ return change;
}
@Override
@@ -470,25 +473,25 @@
int length = initialState.getStateCount();
boolean change;
- boolean[] ensureVirtualized = new boolean[length];
+ BitSet ensureVirtualized = new BitSet(length);
for (int i = 0; i < length; i++) {
ObjectState state = initialState.getObjectStateOptional(i);
if (state != null && state.isVirtual() && state.getEnsureVirtualized()) {
- ensureVirtualized[i] = true;
+ ensureVirtualized.set(i);
}
}
do {
// propagate "ensureVirtualized" flag
change = false;
for (int i = 0; i < length; i++) {
- if (!ensureVirtualized[i]) {
+ if (!ensureVirtualized.get(i)) {
ObjectState state = initialState.getObjectStateOptional(i);
if (state != null && state.isVirtual()) {
for (ValueNode entry : state.getEntries()) {
if (entry instanceof VirtualObjectNode) {
- if (ensureVirtualized[((VirtualObjectNode) entry).getObjectId()]) {
+ if (ensureVirtualized.get(((VirtualObjectNode) entry).getObjectId())) {
change = true;
- ensureVirtualized[i] = true;
+ ensureVirtualized.set(i);
break;
}
}
@@ -500,7 +503,7 @@
for (int i = 0; i < length; i++) {
ObjectState state = initialState.getObjectStateOptional(i);
- if (state != null && state.isVirtual() && !ensureVirtualized[i]) {
+ if (state != null && state.isVirtual() && !ensureVirtualized.get(i)) {
initialState.materializeBefore(end, virtualObjects.get(i), blockEffects.get(loopPredecessor));
}
}
@@ -690,7 +693,6 @@
} else {
for (int object : virtualObjTemp) {
-
if (PartialEscapeBlockState.identicalObjectStates(states, object)) {
newState.addObject(object, states[0].getObjectState(object).share());
continue;
@@ -745,7 +747,7 @@
for (PhiNode phi : getPhis()) {
aliases.set(phi, null);
if (hasVirtualInputs.isMarked(phi) && phi instanceof ValuePhiNode) {
- materialized |= processPhi((ValuePhiNode) phi, states, virtualObjTemp);
+ materialized |= processPhi((ValuePhiNode) phi, states);
}
}
if (materialized) {
@@ -761,31 +763,35 @@
for (int i = 1; i < states.length; i++) {
length = Math.min(length, states[i].getStateCount());
}
- boolean[] result = new boolean[length];
- Arrays.fill(result, true);
- int count = length;
- for (int i = 0; i < states.length; i++) {
- PartialEscapeBlockState<?> state = states[i];
- for (int i2 = 0; i2 < length; i2++) {
- if (result[i2]) {
- if (state.getObjectStateOptional(i2) == null) {
- result[i2] = false;
- count--;
- }
- }
+
+ int count = 0;
+ for (int objectIndex = 0; objectIndex < length; objectIndex++) {
+ if (intersectObjectState(states, objectIndex)) {
+ count++;
}
}
- int[] resultInts = new int[count];
+
int index = 0;
- for (int i = 0; i < length; i++) {
- if (result[i]) {
- resultInts[index++] = i;
+ int[] resultInts = new int[count];
+ for (int objectIndex = 0; objectIndex < length; objectIndex++) {
+ if (intersectObjectState(states, objectIndex)) {
+ resultInts[index++] = objectIndex;
}
}
assert index == count;
return resultInts;
}
+ private boolean intersectObjectState(PartialEscapeBlockState<?>[] states, int objectIndex) {
+ for (int i = 0; i < states.length; i++) {
+ PartialEscapeBlockState<?> state = states[i];
+ if (state.getObjectStateOptional(objectIndex) == null) {
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
* Try to merge multiple virtual object states into a single object state. If the incoming
* object states are compatible, then this method will create PhiNodes for the object's
@@ -960,11 +966,9 @@
*
* @param phi the PhiNode that should be processed
* @param states the predecessor block states of the merge
- * @param mergedVirtualObjects the set of virtual objects that exist in all incoming states,
- * and therefore also exist in the merged state
* @return true if materialization happened during the merge, false otherwise
*/
- private boolean processPhi(ValuePhiNode phi, PartialEscapeBlockState<?>[] states, int[] mergedVirtualObjects) {
+ private boolean processPhi(ValuePhiNode phi, PartialEscapeBlockState<?>[] states) {
// determine how many inputs are virtual and if they're all the same virtual object
int virtualInputs = 0;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java Thu Apr 06 23:01:27 2017 +0000
@@ -115,7 +115,7 @@
}
if (!success) {
TTY.println();
- Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "assertNonReachable");
+ Debug.forceDump(graph, "assertNonReachable");
}
return success;
}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicMap.java Thu Apr 06 22:13:13 2017 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicMap.java Thu Apr 06 23:01:27 2017 +0000
@@ -59,7 +59,7 @@
}
/**
- * Creates a new map that guarantees insertion order on the key set with the the default
+ * Creates a new map that guarantees insertion order on the key set with the default
* {@link Equivalence#DEFAULT} comparison strategy for keys.
*/
static <K, V> EconomicMap<K, V> create() {
@@ -67,7 +67,7 @@
}
/**
- * Creates a new map that guarantees insertion order on the key set with the the default
+ * Creates a new map that guarantees insertion order on the key set with the default
* {@link Equivalence#DEFAULT} comparison strategy for keys and initializes with a specified
* capacity.
*/
@@ -84,7 +84,7 @@
}
/**
- * Creates a new map that guarantees insertion order on the key set with the the default
+ * Creates a new map that guarantees insertion order on the key set with the default
* {@link Equivalence#DEFAULT} comparison strategy for keys and copies all elements from the
* specified existing map.
*/