This commit is contained in:
Igor Veresov 2017-04-06 23:01:27 +00:00
commit 7d637db80c
226 changed files with 4104 additions and 2191 deletions

View File

@ -54,12 +54,9 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.TriState;
public class AOTBackend {
private final Main main;
private final OptionValues graalOptions;
private final HotSpotBackend backend;
private final HotSpotProviders providers;
private final HotSpotCodeCacheProvider codeCache;
private final PhaseSuite<HighTierContext> graphBuilderSuite;
@ -81,6 +78,10 @@ public class AOTBackend {
return graphBuilderSuite;
}
public HotSpotBackend getBackend() {
return backend;
}
private Suites getSuites() {
// create suites every time, as we modify options for the compiler
return backend.getSuites().getDefaultSuites(graalOptions);
@ -189,7 +190,7 @@ public class AOTBackend {
public void printCompiledMethod(HotSpotResolvedJavaMethod resolvedMethod, CompilationResult compResult) {
// This is really not installing the method.
InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(null, null, compResult), null, null);
InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult), null, null);
String disassembly = codeCache.disassemble(installedCode);
if (disassembly != null) {
main.printlnDebug(disassembly);

View File

@ -145,7 +145,7 @@ public class AOTCompilationTask implements Runnable, Comparable<Object> {
aotBackend.printCompiledMethod((HotSpotResolvedJavaMethod) method, compResult);
}
result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method));
result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method, aotBackend.getBackend()));
}
private String getMethodDescription() {

View File

@ -24,6 +24,7 @@
package jdk.tools.jaotc;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
@ -31,9 +32,11 @@ import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
public class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo {
private final HotSpotResolvedJavaMethod method;
private final Backend backend;
public AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method) {
public AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method, Backend backend) {
this.method = method;
this.backend = backend;
}
public String getSymbolName() {
@ -46,7 +49,7 @@ public class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo {
}
public HotSpotCompiledCode compiledCode(CompilationResult result) {
return HotSpotCompiledCodeBuilder.createCompiledCode(method, null, result);
return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), method, null, result);
}
}

View File

@ -49,7 +49,7 @@ public class AOTStub implements JavaMethodInfo {
}
public HotSpotCompiledCode compiledCode(CompilationResult result) {
return HotSpotCompiledCodeBuilder.createCompiledCode(null, null, result);
return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), null, null, result);
}
}

View File

@ -22,15 +22,16 @@
*/
package org.graalvm.compiler.api.directives.test;
import org.junit.Assert;
import org.junit.Test;
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.graph.iterators.NodeIterable;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.IfNode;
import org.graalvm.compiler.nodes.ReturnNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode;
import org.junit.Assert;
import org.junit.Test;
public class ProbabilityDirectiveTest extends GraalCompilerTest {
@ -55,9 +56,21 @@ public class ProbabilityDirectiveTest extends GraalCompilerTest {
Assert.assertEquals("IfNode count", 1, ifNodes.count());
IfNode ifNode = ifNodes.first();
AbstractBeginNode trueSuccessor = ifNode.trueSuccessor();
Assert.assertEquals("branch probability of " + ifNode, 0.125, ifNode.probability(trueSuccessor), 0);
AbstractBeginNode oneSuccessor;
if (returnValue(ifNode.trueSuccessor()) == 1) {
oneSuccessor = ifNode.trueSuccessor();
} else {
assert returnValue(ifNode.falseSuccessor()) == 1;
oneSuccessor = ifNode.falseSuccessor();
}
Assert.assertEquals("branch probability of " + ifNode, 0.125, ifNode.probability(oneSuccessor), 0);
return true;
}
private static int returnValue(AbstractBeginNode b) {
ControlFlowAnchorNode anchor = (ControlFlowAnchorNode) b.next();
ReturnNode returnNode = (ReturnNode) anchor.next();
return returnNode.result().asJavaConstant().asInt();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1757,6 +1757,10 @@ public abstract class SPARCAssembler extends Assembler {
return constant.isNull() || isSimm(constant.asLong(), 5);
}
public static boolean isSimm5(long imm) {
return isSimm(imm, 5);
}
public static boolean isSimm13(int imm) {
return isSimm(imm, 13);
}

View File

@ -35,7 +35,7 @@ public final class TraceStatisticsPrinter {
@SuppressWarnings("try")
public static void printTraceStatistics(TraceBuilderResult result, String compilationUnitName) {
try (Scope s = Debug.scope("DumpTraceStatistics")) {
if (Debug.isLogEnabled(Debug.VERBOSE_LOG_LEVEL)) {
if (Debug.isLogEnabled(Debug.VERBOSE_LEVEL)) {
print(result, compilationUnitName);
}
} catch (Throwable e) {
@ -48,9 +48,9 @@ public final class TraceStatisticsPrinter {
List<Trace> traces = result.getTraces();
int numTraces = traces.size();
try (Indent indent0 = Debug.logAndIndent(Debug.VERBOSE_LOG_LEVEL, "<tracestatistics>")) {
Debug.log(Debug.VERBOSE_LOG_LEVEL, "<name>%s</name>", compilationUnitName != null ? compilationUnitName : "null");
try (Indent indent1 = Debug.logAndIndent(Debug.VERBOSE_LOG_LEVEL, "<traces>")) {
try (Indent indent0 = Debug.logAndIndent(Debug.VERBOSE_LEVEL, "<tracestatistics>")) {
Debug.log(Debug.VERBOSE_LEVEL, "<name>%s</name>", compilationUnitName != null ? compilationUnitName : "null");
try (Indent indent1 = Debug.logAndIndent(Debug.VERBOSE_LEVEL, "<traces>")) {
printRawLine("tracenumber", "total", "min", "max", "numBlocks");
for (int i = 0; i < numTraces; i++) {
AbstractBlockBase<?>[] t = traces.get(i).getBlocks();
@ -70,14 +70,14 @@ public final class TraceStatisticsPrinter {
printLine(i, total, min, max, t.length);
}
}
Debug.log(Debug.VERBOSE_LOG_LEVEL, "</traces>");
Debug.log(Debug.VERBOSE_LEVEL, "</traces>");
}
Debug.log(Debug.VERBOSE_LOG_LEVEL, "</tracestatistics>");
Debug.log(Debug.VERBOSE_LEVEL, "</tracestatistics>");
}
private static void printRawLine(Object tracenr, Object totalTime, Object minProb, Object maxProb, Object numBlocks) {
Debug.log(Debug.VERBOSE_LOG_LEVEL, "%s", String.join(SEP, tracenr.toString(), totalTime.toString(), minProb.toString(), maxProb.toString(), numBlocks.toString()));
Debug.log(Debug.VERBOSE_LEVEL, "%s", String.join(SEP, tracenr.toString(), totalTime.toString(), minProb.toString(), maxProb.toString(), numBlocks.toString()));
}
private static void printLine(int tracenr, double totalTime, double minProb, double maxProb, int numBlocks) {

View File

@ -343,6 +343,33 @@ public enum Condition {
if (lt instanceof PrimitiveConstant) {
PrimitiveConstant lp = (PrimitiveConstant) lt;
PrimitiveConstant rp = (PrimitiveConstant) rt;
return foldCondition(lp, rp, unorderedIsTrue);
} else {
Boolean equal = constantReflection.constantEquals(lt, rt);
if (equal == null) {
throw new GraalError("could not fold %s %s %s", lt, this, rt);
}
switch (this) {
case EQ:
return equal.booleanValue();
case NE:
return !equal.booleanValue();
default:
throw new GraalError("expected condition: %s", this);
}
}
}
/**
* Attempts to fold a comparison between two primitive constants and return the result.
*
* @param lp the constant on the left side of the comparison
* @param rp the constant on the right side of the comparison
* @param unorderedIsTrue true if an undecided float comparison should result in "true"
* @return true if the comparison is known to be true, false if the comparison is known to be
* false
*/
public boolean foldCondition(PrimitiveConstant lp, PrimitiveConstant rp, boolean unorderedIsTrue) {
switch (lp.getJavaKind()) {
case Boolean:
case Byte:
@ -453,20 +480,6 @@ public enum Condition {
default:
throw new GraalError("expected value kind %s while folding condition: %s", lp.getJavaKind(), this);
}
} else {
Boolean equal = constantReflection.constantEquals(lt, rt);
if (equal == null) {
throw new GraalError("could not fold %s %s %s", lt, this, rt);
}
switch (this) {
case EQ:
return equal.booleanValue();
case NE:
return !equal.booleanValue();
default:
throw new GraalError("expected condition: %s", this);
}
}
}
public Condition join(Condition other) {

View File

@ -154,6 +154,7 @@ public class FloatStamp extends PrimitiveStamp {
return Double.isNaN(lowerBound);
}
@Override
public boolean isUnrestricted() {
return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN;
}

View File

@ -58,6 +58,11 @@ public final class IllegalStamp extends Stamp {
return this;
}
@Override
public boolean isUnrestricted() {
return true;
}
@Override
public Stamp empty() {
return this;

View File

@ -254,6 +254,7 @@ public final class IntegerStamp extends PrimitiveStamp {
return upMask;
}
@Override
public boolean isUnrestricted() {
return lowerBound == CodeUtil.minValue(getBits()) && upperBound == CodeUtil.maxValue(getBits()) && downMask == 0 && upMask == CodeUtil.mask(getBits());
}

View File

@ -125,6 +125,13 @@ public abstract class Stamp {
return !hasValues();
}
/**
* Tests whether this stamp represents all values of this kind.
*/
public boolean isUnrestricted() {
return this.equals(this.unrestricted());
}
/**
* If this stamp represents a single value, the methods returns this single value. It returns
* null otherwise.

View File

@ -39,33 +39,6 @@ import jdk.vm.ci.meta.Signature;
public class StampFactory {
/*
* The marker stamp for node intrinsics must be its own class, so that it is never equal() to a
* regular ObjectStamp.
*/
static final class NodeIntrinsicStamp extends ObjectStamp {
protected static final Stamp SINGLETON = new NodeIntrinsicStamp();
private NodeIntrinsicStamp() {
super(null, false, false, false);
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
@Override
public boolean equals(Object obj) {
return this == obj;
}
@Override
public String toString() {
return "NodeIntrinsicStamp";
}
}
// JaCoCo Exclude
private static final Stamp[] stampCache = new Stamp[JavaKind.values().length];
@ -143,14 +116,6 @@ public class StampFactory {
return VoidStamp.getInstance();
}
/**
* A stamp used only in the graph of intrinsics, e.g., snippets. It is then replaced by an
* actual stamp when the intrinsic is used, i.e., when the snippet template is instantiated.
*/
public static Stamp forNodeIntrinsic() {
return NodeIntrinsicStamp.SINGLETON;
}
public static Stamp intValue() {
return forKind(JavaKind.Int);
}

View File

@ -45,6 +45,11 @@ public final class VoidStamp extends Stamp {
return this;
}
@Override
public boolean isUnrestricted() {
return true;
}
@Override
public JavaKind getStackKind() {
return JavaKind.Void;

View File

@ -23,10 +23,10 @@
package org.graalvm.compiler.core.common.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import org.graalvm.util.EconomicMap;
import org.graalvm.util.Equivalence;
/**
* Creates an array of T objects order by the occurrence frequency of each object. The most
@ -49,24 +49,24 @@ public class FrequencyEncoder<T> {
}
}
protected final Map<T, Entry<T>> map;
protected final EconomicMap<T, Entry<T>> map;
protected boolean containsNull;
/**
* Creates an encoder that uses object identity.
*/
public static <T> FrequencyEncoder<T> createIdentityEncoder() {
return new FrequencyEncoder<>(new IdentityHashMap<>());
return new FrequencyEncoder<>(EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE));
}
/**
* Creates an encoder that uses {@link Object#equals(Object) object equality}.
*/
public static <T> FrequencyEncoder<T> createEqualityEncoder() {
return new FrequencyEncoder<>(new HashMap<>());
return new FrequencyEncoder<>(EconomicMap.create(Equivalence.DEFAULT));
}
protected FrequencyEncoder(Map<T, Entry<T>> map) {
protected FrequencyEncoder(EconomicMap<T, Entry<T>> map) {
this.map = map;
}
@ -91,7 +91,7 @@ public class FrequencyEncoder<T> {
* Returns the index of an object in the array. The object must have been
* {@link #addObject(Object) added} before.
*/
public int getIndex(Object object) {
public int getIndex(T object) {
if (object == null) {
assert containsNull;
return 0;
@ -114,7 +114,10 @@ public class FrequencyEncoder<T> {
*/
public T[] encodeAll(T[] allObjects) {
assert allObjects.length == getLength();
List<Entry<T>> sortedEntries = new ArrayList<>(map.values());
List<Entry<T>> sortedEntries = new ArrayList<>(allObjects.length);
for (Entry<T> value : map.getValues()) {
sortedEntries.add(value);
}
sortedEntries.sort((e1, e2) -> -Integer.compare(e1.frequency, e2.frequency));
int offset = 0;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -202,7 +202,7 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator {
private Variable emitUnary(Op3s op3, Value input) {
Variable result = getLIRGen().newVariable(LIRKind.combine(input));
getLIRGen().append(SPARCOP3Op.newUnary(op3, input, result));
getLIRGen().append(SPARCOP3Op.newUnary(op3, getLIRGen().loadSimm13(input), result));
return result;
}
@ -227,9 +227,9 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator {
private Variable emitBinary(ValueKind<?> resultKind, Op3s op3, Value a, Value b, LIRFrameState state) {
Variable result = getLIRGen().newVariable(resultKind);
if (op3.isCommutative() && isJavaConstant(a) && getLIRGen().getMoveFactory().canInlineConstant(asJavaConstant(a))) {
getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(b), a, result, state));
getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(b), getLIRGen().loadSimm13(a), result, state));
} else {
getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(a), b, result, state));
getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(a), getLIRGen().loadSimm13(b), result, state));
}
return result;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -199,11 +199,11 @@ public abstract class SPARCLIRGenerator extends LIRGenerator {
Condition actualCondition;
if (isJavaConstant(x)) {
left = load(y);
right = loadNonConst(x);
right = loadSimm13(x);
actualCondition = cond.mirror();
} else {
left = load(x);
right = loadNonConst(y);
right = loadSimm13(y);
actualCondition = cond;
}
SPARCKind actualCmpKind = (SPARCKind) cmpKind;
@ -250,7 +250,7 @@ public abstract class SPARCLIRGenerator extends LIRGenerator {
return load(value);
}
private Value loadSimm13(Value value) {
public Value loadSimm13(Value value) {
if (isJavaConstant(value)) {
JavaConstant c = asJavaConstant(value);
if (c.isNull() || SPARCAssembler.isSimm13(c)) {
@ -260,6 +260,13 @@ public abstract class SPARCLIRGenerator extends LIRGenerator {
return load(value);
}
@Override
public Value loadNonConst(Value value) {
// SPARC does not support a proper way of loadNonConst. Please use the appropriate
// loadSimm11 or loadSimm13 variants.
throw GraalError.shouldNotReachHere("This operation is not available for SPARC.");
}
@Override
public Variable emitConditionalMove(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
// Emit compare

View File

@ -22,10 +22,6 @@
*/
package org.graalvm.compiler.core.test;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.graalvm.compiler.loop.DefaultLoopPolicies;
import org.graalvm.compiler.loop.phases.LoopPeelingPhase;
import org.graalvm.compiler.nodes.ReturnNode;
@ -37,6 +33,9 @@ import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
import org.graalvm.compiler.phases.common.inlining.InliningPhase;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
/**
* In the following tests, the usages of local variable "a" are replaced with the integer constant
@ -162,7 +161,7 @@ public class BoxingEliminationTest extends GraalCompilerTest {
sum0 = a;
} else {
int sum = a;
for (int i = 0; i < n; i++) {
for (int i = 1; i < n; i++) {
sum += i;
}
sum0 = sum;

View File

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

View File

@ -32,8 +32,8 @@ import org.junit.Test;
public class ConditionalEliminationMulTest extends GraalCompilerTest {
public static void snippet01(int a) {
if (a == 2) {
if (a * 3 != 6) {
if (a == 3) {
if (a * 11 != 33) {
shouldBeOptimizedAway();
}
}
@ -41,7 +41,7 @@ public class ConditionalEliminationMulTest extends GraalCompilerTest {
public static void snippet02(int a) {
if (a == 0) {
if (a * 3 != 0) {
if (a * 11 != 0) {
shouldBeOptimizedAway();
}
}

View File

@ -22,9 +22,8 @@
*/
package org.graalvm.compiler.core.test;
import org.junit.Test;
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.junit.Test;
/**
* Collection of tests for
@ -32,15 +31,16 @@ import org.graalvm.compiler.api.directives.GraalDirectives;
* that triggered bugs in this phase.
*/
public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase {
protected static int sink3;
private static final String REFERENCE_SNIPPET = "referenceSnippet";
@SuppressWarnings("all")
public static int referenceSnippet(int a) {
public static void referenceSnippet(int a) {
if (a == 0) {
return 1;
sink1 = 1;
}
return 0;
sink0 = 0;
}
@Test
@ -49,21 +49,21 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase
}
@SuppressWarnings("all")
public static int test1Snippet(int a) {
public static void test1Snippet(int a) {
if (a == 0) {
if (a == 5) {
return 100;
sink2 = 100;
}
if (a > 100) {
if (a == 0) {
return 200;
sink3 = 200;
}
}
if (a != 2) {
return 1;
sink1 = 1;
}
}
return 0;
sink0 = 0;
}
@Test
@ -72,18 +72,18 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase
}
@SuppressWarnings("all")
public static int test2Snippet(int a) {
public static void test2Snippet(int a) {
if (a == 0) {
if (a > 100) {
if (a == 0) {
return 200;
sink3 = 200;
}
}
if (a != 2) {
return 1;
sink1 = 1;
}
}
return 0;
sink0 = 0;
}
@Test
@ -92,7 +92,7 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase
}
@SuppressWarnings("all")
public static int test3Snippet(int a) {
public static void test3Snippet(int a) {
if (a == 0) {
if (a < 1) {
if (a < 2) {
@ -101,9 +101,9 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase
if (a > -2) {
if (a > -3) {
if (a == 1) {
return 42;
sink2 = 42;
} else {
return 1;
sink1 = 1;
}
}
}
@ -112,18 +112,18 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase
}
}
}
return 0;
sink0 = 0;
}
@SuppressWarnings("all")
public static int test4Snippet(int a, int b) {
public static void test4Snippet(int a, int b) {
if (b < 1) {
GraalDirectives.controlFlowAnchor();
if (b < 0) {
return 1;
sink1 = 1;
}
}
return 0;
sink0 = 0;
}
@Test
@ -132,21 +132,21 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase
}
@SuppressWarnings("all")
public static int test5Snippet(int a, int b) {
public static void test5Snippet(int a, int b) {
if ((b & 3) == 0) {
GraalDirectives.controlFlowAnchor();
if ((b & 7) == 0) {
GraalDirectives.controlFlowAnchor();
return 1;
sink1 = 1;
}
} else {
GraalDirectives.controlFlowAnchor();
if ((b & 1) == 0) {
GraalDirectives.controlFlowAnchor();
return 2;
sink2 = 2;
}
}
return 0;
sink0 = 0;
}
@Test

View File

@ -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) {

View File

@ -34,13 +34,6 @@ import org.junit.Test;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public class ConditionalEliminationTest13 extends ConditionalEliminationTestBase {
public ConditionalEliminationTest13() {
super(false);
}
private static int sink0;
private static int sink1;
private static int sink2;
@Override
protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
@ -317,7 +310,7 @@ public class ConditionalEliminationTest13 extends ConditionalEliminationTestBase
super.prepareGraph(graph, canonicalizer, context, applyLowering);
graph.clearAllStateAfter();
graph.setGuardsStage(StructuredGraph.GuardsStage.AFTER_FSA);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After preparation");
Debug.dump(Debug.BASIC_LEVEL, graph, "After preparation");
canonicalizer.apply(graph, context);
}
}

View File

@ -22,11 +22,10 @@
*/
package org.graalvm.compiler.core.test;
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.junit.Ignore;
import org.junit.Test;
import org.graalvm.compiler.api.directives.GraalDirectives;
/**
* Collection of tests for
* {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those
@ -50,20 +49,20 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase
static final class DistinctB {
}
public static int reference1Snippet(Object a) {
public static void reference1Snippet(Object a) {
if (a instanceof B) {
return 1;
sink1 = 1;
}
return 2;
sink2 = 2;
}
public static int test1Snippet(Object a) {
public static void test1Snippet(Object a) {
if (a instanceof B) {
if (a instanceof A) {
return 1;
sink1 = 1;
}
}
return 2;
sink2 = 2;
}
@Test
@ -71,21 +70,21 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase
testConditionalElimination("test1Snippet", "reference1Snippet");
}
public static int reference2Snippet(A a) {
public static void reference2Snippet(A a) {
if (a instanceof B) {
return 1;
sink1 = 1;
}
return 2;
sink2 = 2;
}
public static int test2Snippet(A a) {
public static void test2Snippet(A a) {
if (a instanceof B) {
B newVal = (B) a;
if (newVal != null) {
return 1;
sink1 = 1;
}
}
return 2;
sink2 = 2;
}
@Test
@ -94,28 +93,28 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase
}
@SuppressWarnings("unused")
public static int reference3Snippet(Object a, Object b) {
public static void reference3Snippet(Object a, Object b) {
if (a instanceof DistinctA) {
DistinctA proxyA = (DistinctA) a;
if (b instanceof DistinctB) {
return 1;
sink1 = 1;
}
}
return 2;
sink2 = 2;
}
@SuppressWarnings("all")
public static int test3Snippet(Object a, Object b) {
public static void test3Snippet(Object a, Object b) {
if (a instanceof DistinctA) {
DistinctA proxyA = (DistinctA) a;
if (b instanceof DistinctB) {
if (proxyA == b) {
return 42;
sink0 = 42;
}
return 1;
sink1 = 1;
}
}
return 2;
sink2 = 2;
}
@Test
@ -123,54 +122,54 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase
testConditionalElimination("test3Snippet", "reference3Snippet", true, false);
}
public static int reference4Snippet(Object a) {
public static void reference4Snippet(Object a) {
if (!(a instanceof B)) {
GraalDirectives.deoptimizeAndInvalidate();
}
return 1;
sink1 = 1;
}
public static int test4Snippet1(Object a) {
public static void test4Snippet1(Object a) {
if (!(a instanceof B)) {
GraalDirectives.deoptimizeAndInvalidate();
}
if (!(a instanceof A)) {
GraalDirectives.deoptimizeAndInvalidate();
}
return 1;
sink1 = 1;
}
public static int test4Snippet2(Object a) {
public static void test4Snippet2(Object a) {
if (!(a instanceof A)) {
GraalDirectives.deoptimizeAndInvalidate();
}
if (!(a instanceof B)) {
GraalDirectives.deoptimizeAndInvalidate();
}
return 1;
sink1 = 1;
}
@SuppressWarnings({"cast", "unused"})
public static int test4Snippet3(Object a) {
public static void test4Snippet3(Object a) {
Object pi = (A) a;
if (!(a instanceof B)) {
GraalDirectives.deoptimizeAndInvalidate();
}
return 1;
sink1 = 1;
}
public static int test4Snippet4(Object a) {
public static void test4Snippet4(Object a) {
if (!(a instanceof A)) {
GraalDirectives.deoptimizeAndInvalidate();
}
if (!(((A) a) instanceof B)) {
GraalDirectives.deoptimizeAndInvalidate();
}
return 1;
sink1 = 1;
}
@SuppressWarnings({"cast"})
public static int test4Snippet5(Object a) {
public static void test4Snippet5(Object a) {
Object pi = (A) a;
if (pi == null) {
GraalDirectives.deoptimizeAndInvalidate();
@ -178,7 +177,7 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase
if (!(a instanceof B)) {
GraalDirectives.deoptimizeAndInvalidate();
}
return 1;
sink1 = 1;
}
@Test

View File

@ -42,15 +42,9 @@ import org.junit.Assert;
* that triggered bugs in this phase.
*/
public class ConditionalEliminationTestBase extends GraalCompilerTest {
private final boolean disableSimplification;
protected ConditionalEliminationTestBase() {
this(true);
}
protected ConditionalEliminationTestBase(boolean disableSimplification) {
this.disableSimplification = disableSimplification;
}
protected static int sink0;
protected static int sink1;
protected static int sink2;
protected void testConditionalElimination(String snippet, String referenceSnippet) {
testConditionalElimination(snippet, referenceSnippet, false, false);
@ -59,15 +53,9 @@ public class ConditionalEliminationTestBase extends GraalCompilerTest {
@SuppressWarnings("try")
protected void testConditionalElimination(String snippet, String referenceSnippet, boolean applyConditionalEliminationOnReference, boolean applyLowering) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
PhaseContext context = new PhaseContext(getProviders());
CanonicalizerPhase canonicalizer1 = new CanonicalizerPhase();
if (disableSimplification) {
/**
* Some tests break if simplification is done so only do it when needed.
*/
canonicalizer1.disableSimplification();
}
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
try (Debug.Scope scope = Debug.scope("ConditionalEliminationTest", graph)) {
prepareGraph(graph, canonicalizer1, context, applyLowering);

View File

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

View File

@ -86,9 +86,9 @@ public class DegeneratedLoopsTest extends GraalCompilerTest {
HighTierContext context = getDefaultHighTierContext();
new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
new CanonicalizerPhase().apply(graph, context);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES);
Debug.dump(Debug.BASIC_LOG_LEVEL, referenceGraph, "ReferenceGraph");
Debug.dump(Debug.BASIC_LEVEL, referenceGraph, "ReferenceGraph");
assertEquals(referenceGraph, graph);
} catch (Throwable e) {
throw Debug.handle(e);

View File

@ -142,7 +142,7 @@ public class FindUniqueDefaultMethodTest extends GraalCompilerTest {
try (Scope s = Debug.scope("InstanceOfTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
compile(graph.method(), graph);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet);
Debug.dump(Debug.BASIC_LEVEL, graph, snippet);
return graph;
} catch (Throwable e) {
throw Debug.handle(e);

View File

@ -82,7 +82,7 @@ public class FloatingReadTest extends GraphScheduleTest {
}
}
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After lowering");
Debug.dump(Debug.BASIC_LEVEL, graph, "After lowering");
Assert.assertNotNull(returnNode);
Assert.assertNotNull(monitorexit);

View File

@ -78,6 +78,7 @@ import org.graalvm.compiler.nodes.FrameState;
import org.graalvm.compiler.nodes.FullInfopointNode;
import org.graalvm.compiler.nodes.InvokeNode;
import org.graalvm.compiler.nodes.InvokeWithExceptionNode;
import org.graalvm.compiler.nodes.ParameterNode;
import org.graalvm.compiler.nodes.ProxyNode;
import org.graalvm.compiler.nodes.ReturnNode;
import org.graalvm.compiler.nodes.StructuredGraph;
@ -91,6 +92,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.nodes.java.AccessFieldNode;
import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.nodes.spi.Replacements;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
@ -121,6 +123,7 @@ import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.InstalledCode;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.Assumptions.Assumption;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.DeoptimizationReason;
import jdk.vm.ci.meta.JavaKind;
@ -130,7 +133,6 @@ import jdk.vm.ci.meta.ProfilingInfo;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.SpeculationLog;
import jdk.vm.ci.meta.Assumptions.Assumption;
import jdk.vm.ci.services.Services;
/**
@ -410,13 +412,13 @@ public abstract class GraalCompilerTest extends GraalTest {
String mismatchString = compareGraphStrings(expected, expectedString, graph, actualString);
if (!excludeVirtual && getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) {
Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "Node count not matching - expected");
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Node count not matching - actual");
Debug.dump(Debug.BASIC_LEVEL, expected, "Node count not matching - expected");
Debug.dump(Debug.BASIC_LEVEL, graph, "Node count not matching - actual");
Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount() + "\n" + mismatchString);
}
if (!expectedString.equals(actualString)) {
Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "mismatching graphs - expected");
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "mismatching graphs - actual");
Debug.dump(Debug.BASIC_LEVEL, expected, "mismatching graphs - expected");
Debug.dump(Debug.BASIC_LEVEL, graph, "mismatching graphs - actual");
Assert.fail(mismatchString);
}
}
@ -482,22 +484,25 @@ public abstract class GraalCompilerTest extends GraalTest {
StringBuilder result = new StringBuilder();
for (Block block : scheduleResult.getCFG().getBlocks()) {
result.append("Block " + block + " ");
result.append("Block ").append(block).append(' ');
if (block == scheduleResult.getCFG().getStartBlock()) {
result.append("* ");
}
result.append("-> ");
for (Block succ : block.getSuccessors()) {
result.append(succ + " ");
result.append(succ).append(' ');
}
result.append("\n");
result.append('\n');
for (Node node : scheduleResult.getBlockToNodesMap().get(block)) {
if (node instanceof ValueNode && node.isAlive()) {
if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode || node instanceof FullInfopointNode)) {
if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode || node instanceof FullInfopointNode || node instanceof ParameterNode)) {
if (node instanceof ConstantNode) {
String name = checkConstants ? node.toString(Verbosity.Name) : node.getClass().getSimpleName();
String str = name + (excludeVirtual ? "\n" : " (" + filteredUsageCount(node) + ")\n");
constantsLines.add(str);
if (excludeVirtual) {
constantsLines.add(name);
} else {
constantsLines.add(name + " (" + filteredUsageCount(node) + ")");
}
} else {
int id;
if (canonicalId.get(node) != null) {
@ -507,8 +512,17 @@ public abstract class GraalCompilerTest extends GraalTest {
canonicalId.set(node, id);
}
String name = node.getClass().getSimpleName();
String str = " " + id + "|" + name + (excludeVirtual ? "\n" : " (" + filteredUsageCount(node) + ")\n");
result.append(str);
result.append(" ").append(id).append('|').append(name);
if (node instanceof AccessFieldNode) {
result.append('#');
result.append(((AccessFieldNode) node).field());
}
if (!excludeVirtual) {
result.append(" (");
result.append(filteredUsageCount(node));
result.append(')');
}
result.append('\n');
}
}
}
@ -516,14 +530,14 @@ public abstract class GraalCompilerTest extends GraalTest {
}
StringBuilder constantsLinesResult = new StringBuilder();
constantsLinesResult.append(constantsLines.size() + " constants:\n");
constantsLinesResult.append(constantsLines.size()).append(" constants:\n");
Collections.sort(constantsLines);
for (String s : constantsLines) {
constantsLinesResult.append(s);
constantsLinesResult.append("\n");
constantsLinesResult.append('\n');
}
return constantsLines.toString() + result.toString();
return constantsLinesResult.toString() + result.toString();
}
/**
@ -545,15 +559,15 @@ public abstract class GraalCompilerTest extends GraalTest {
StringBuilder result = new StringBuilder();
Block[] blocks = scheduleResult.getCFG().getBlocks();
for (Block block : blocks) {
result.append("Block " + block + " ");
result.append("Block ").append(block).append(' ');
if (block == scheduleResult.getCFG().getStartBlock()) {
result.append("* ");
}
result.append("-> ");
for (Block succ : block.getSuccessors()) {
result.append(succ + " ");
result.append(succ).append(' ');
}
result.append("\n");
result.append('\n');
for (Node node : scheduleResult.getBlockToNodesMap().get(block)) {
result.append(String.format("%1S\n", node));
}

View File

@ -217,7 +217,7 @@ public class IfCanonicalizerTest extends GraalCompilerTest {
n.replaceFirstInput(param, constant);
}
}
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
for (FrameState fs : param.usages().filter(FrameState.class).snapshot()) {
fs.replaceFirstInput(param, null);

View File

@ -25,7 +25,8 @@ package org.graalvm.compiler.core.test;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import org.junit.Test;
import org.graalvm.compiler.loop.DefaultLoopPolicies;
import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.java.MonitorExitNode;
@ -91,6 +92,26 @@ public class LockEliminationTest extends GraalCompilerTest {
assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
}
public void testUnrolledSyncSnippet(Object a) {
for (int i = 0; i < 3; i++) {
synchronized (a) {
}
}
}
@Test
public void testUnrolledSync() {
StructuredGraph graph = getGraph("testUnrolledSyncSnippet");
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
canonicalizer.apply(graph, new PhaseContext(getProviders()));
HighTierContext context = getDefaultHighTierContext();
new LoopFullUnrollPhase(canonicalizer, new DefaultLoopPolicies()).apply(graph, context);
new LockEliminationPhase().apply(graph);
assertDeepEquals(1, graph.getNodes().filter(RawMonitorEnterNode.class).count());
assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
}
private StructuredGraph getGraph(String snippet) {
ResolvedJavaMethod method = getResolvedJavaMethod(snippet);
StructuredGraph graph = parseEager(method, AllowAssumptions.YES);

View File

@ -717,7 +717,7 @@ public class MemoryScheduleTest extends GraphScheduleTest {
if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
graph.clearAllStateAfter();
}
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "after removal of framestates");
Debug.dump(Debug.BASIC_LEVEL, graph, "after removal of framestates");
new FloatingReadPhase().apply(graph);
new RemoveValueProxyPhase().apply(graph);

View File

@ -61,7 +61,7 @@ public class MergeCanonicalizerTest extends GraalCompilerTest {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
assertDeepEquals(returnCount, graph.getNodes(ReturnNode.TYPE).count());
}
}

View File

@ -142,7 +142,7 @@ public class NestedLoopTest extends GraalCompilerTest {
private void test(String snippet, int rootExits, int nestedExits, int innerExits) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
Assert.assertEquals(3, cfg.getLoops().size());
@ -162,7 +162,7 @@ public class NestedLoopTest extends GraalCompilerTest {
Assert.assertEquals(rootExits, rootLoop.getExits().size());
Assert.assertEquals(nestedExits, nestedLoop.getExits().size());
Assert.assertEquals(innerExits, innerMostLoop.getExits().size());
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
}
private static boolean contains(Loop<Block> loop, Invoke node, ControlFlowGraph cfg) {

View File

@ -58,9 +58,11 @@ public class NodePropertiesTest extends GraalCompilerTest {
x = 2;
sideEffect = null;
}
int b = 4;
sideEffect = null;
int c = b % 5;
// can shift
return a * x * 4;
return a * x * c;
}
public static int test2Snippet(int a) {
@ -249,7 +251,7 @@ public class NodePropertiesTest extends GraalCompilerTest {
gc2.apply(g2, htc);
Debug.log("Test Graph Cost --> 1.Graph cost:%f vs. 2.Graph cost:%f\n", gc1.finalCycles, gc2.finalCycles);
Assert.assertTrue(gc2.finalCycles > gc1.finalCycles);
Assert.assertTrue(gc2.finalSize == gc1.finalSize + 1/* mul has 3 const input */);
Assert.assertTrue(gc2.finalSize == gc1.finalSize);
}
@Test

View File

@ -70,7 +70,7 @@ public class PhiCreationTests extends GraalCompilerTest {
@Test
public void test3() {
StructuredGraph graph = parseEager("test3Snippet", AllowAssumptions.YES);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext());
}
@ -86,7 +86,7 @@ public class PhiCreationTests extends GraalCompilerTest {
@Test
public void test4() {
StructuredGraph graph = parseEager("test4Snippet", AllowAssumptions.YES);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext());
}

View File

@ -59,7 +59,7 @@ public class PushThroughIfTest extends GraalCompilerTest {
private void test(String snippet, String reference) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
for (FrameState fs : graph.getNodes(FrameState.TYPE).snapshot()) {
fs.replaceAtUsages(null);
GraphUtil.killWithUnusedFloatingInputs(fs);

View File

@ -94,7 +94,7 @@ public class ReadAfterCheckCastTest extends GraphScheduleTest {
new FloatingReadPhase().apply(graph);
canonicalizer.apply(graph, context);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After lowering");
Debug.dump(Debug.BASIC_LEVEL, graph, "After lowering");
for (FloatingReadNode node : graph.getNodes(ParameterNode.TYPE).first().usages().filter(FloatingReadNode.class)) {
// Checking that the parameter a is not directly used for the access to field

View File

@ -131,7 +131,7 @@ public class ScalarTypeSystemTest extends GraalCompilerTest {
private void test(final String snippet, final String referenceSnippet) {
// No debug scope to reduce console noise for @Test(expected = ...) tests
StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
PhaseContext context = new PhaseContext(getProviders());
new CanonicalizerPhase().apply(graph, context);
StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO);

View File

@ -69,7 +69,7 @@ public class SchedulingTest2 extends GraphScheduleTest {
BeginNode beginNode = graph.add(new BeginNode());
returnNode.replaceAtPredecessor(beginNode);
beginNode.setNext(returnNode);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST);
schedulePhase.apply(graph);
ScheduleResult schedule = graph.getLastSchedule();

View File

@ -41,7 +41,7 @@ import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
public class SimpleCFGTest extends GraalCompilerTest {
private static void dumpGraph(final StructuredGraph graph) {
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
}
@Test

View File

@ -88,7 +88,7 @@ public class StraighteningTest extends GraalCompilerTest {
private void test(final String snippet) {
// No debug scope to reduce console noise for @Test(expected = ...) tests
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES);
assertEquals(referenceGraph, graph);

View File

@ -180,7 +180,7 @@ public class TypeSystemTest extends GraalCompilerTest {
private void test(String snippet, String referenceSnippet) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
/*
* When using FlowSensitiveReductionPhase instead of ConditionalEliminationPhase,
* tail-duplication gets activated thus resulting in a graph with more nodes than the
@ -200,8 +200,8 @@ public class TypeSystemTest extends GraalCompilerTest {
@Override
protected void assertEquals(StructuredGraph expected, StructuredGraph graph) {
if (getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) {
Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "expected (node count)");
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "graph (node count)");
Debug.dump(Debug.BASIC_LEVEL, expected, "expected (node count)");
Debug.dump(Debug.BASIC_LEVEL, graph, "graph (node count)");
Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount());
}
}
@ -244,7 +244,7 @@ public class TypeSystemTest extends GraalCompilerTest {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph " + snippet);
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph " + snippet);
Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext());
}
}

View File

@ -83,9 +83,28 @@ public class VerifyDebugUsageTest {
@Override
protected void run(StructuredGraph graph) {
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "%s", graph.toString());
Debug.dump(Debug.BASIC_LEVEL, graph, "%s", graph.toString());
}
}
private static class InvalidDumpLevelPhase extends Phase {
@Override
protected void run(StructuredGraph graph) {
Debug.dump(Debug.VERY_DETAILED_LEVEL + 1, graph, "%s", graph);
}
}
private static class NonConstantDumpLevelPhase extends Phase {
@Override
protected void run(StructuredGraph graph) {
Debug.dump(getLevel(), graph, "%s", graph);
}
int getLevel() {
return 10;
}
}
private static class InvalidVerifyUsagePhase extends Phase {
@ -126,7 +145,7 @@ public class VerifyDebugUsageTest {
@Override
protected void run(StructuredGraph graph) {
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "error " + graph);
Debug.dump(Debug.BASIC_LEVEL, graph, "error " + graph);
}
}
@ -169,7 +188,7 @@ public class VerifyDebugUsageTest {
@Override
protected void run(StructuredGraph graph) {
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "%s", graph);
Debug.dump(Debug.BASIC_LEVEL, graph, "%s", graph);
}
}
@ -233,6 +252,16 @@ public class VerifyDebugUsageTest {
testDebugUsageClass(InvalidDumpUsagePhase.class);
}
@Test(expected = VerificationError.class)
public void testDumpLevelInvalid() {
testDebugUsageClass(InvalidDumpLevelPhase.class);
}
@Test(expected = VerificationError.class)
public void testDumpNonConstantLevelInvalid() {
testDebugUsageClass(NonConstantDumpLevelPhase.class);
}
@Test(expected = VerificationError.class)
public void testLogInvalidConcat() {
testDebugUsageClass(InvalidConcatLogUsagePhase.class);

View File

@ -135,6 +135,7 @@ public class PartialEscapeAnalysisTest extends EATestBase {
}
public static Object[] array = new Object[]{1, 2, 3, 4, 5, "asdf", "asdf"};
public static char[] charArray = new char[]{1, 2, 3, 4, 5, 'a', 'f'};
public static Object testArrayCopySnippet(int a) {
Object[] tmp = new Object[]{a != 1 ? array[a] : null};
@ -143,6 +144,18 @@ public class PartialEscapeAnalysisTest extends EATestBase {
return tmp2[4];
}
@Test
public void testPrimitiveArraycopy() {
testPartialEscapeAnalysis("testPrimitiveArraycopySnippet", 0, 0);
}
public static Object testPrimitiveArraycopySnippet(int a) {
char[] tmp = new char[]{a != 1 ? charArray[a] : 0};
char[] tmp2 = new char[5];
System.arraycopy(tmp, 0, tmp2, 4, 1);
return tmp2[4];
}
@Test
@Ignore
public void testCache() {

View File

@ -244,10 +244,10 @@ public class InliningTest extends GraalCompilerTest {
? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true))
: getDefaultGraphBuilderSuite();
HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
new CanonicalizerPhase().apply(graph, context);
new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph");
Debug.dump(Debug.BASIC_LEVEL, graph, "Graph");
new CanonicalizerPhase().apply(graph, context);
new DeadCodeEliminationPhase().apply(graph);
return graph;

View File

@ -121,7 +121,7 @@ public class NestedLoopEffectsPhaseComplexityTest extends GraalCompilerTest {
long start = System.currentTimeMillis();
phase.apply(g, context);
long end = System.currentTimeMillis();
Debug.dump(Debug.DETAILED_LOG_LEVEL, g, "After %s", phase.contractorName());
Debug.dump(Debug.DETAILED_LEVEL, g, "After %s", phase.contractorName());
return end - start;
}
@ -138,7 +138,7 @@ public class NestedLoopEffectsPhaseComplexityTest extends GraalCompilerTest {
next = callerGraph.getNodes(MethodCallTargetNode.TYPE).first().invoke();
EconomicSet<Node> canonicalizeNodes = InliningUtil.inlineForCanonicalization(next, calleeGraph, false, calleeMethod);
canonicalizer.applyIncremental(callerGraph, context, canonicalizeNodes);
Debug.dump(Debug.DETAILED_LOG_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i);
Debug.dump(Debug.DETAILED_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i);
}
return callerGraph;
}

View File

@ -25,6 +25,8 @@ package org.graalvm.compiler.core.test.tutorial;
import org.junit.Assert;
import org.junit.Test;
import java.util.regex.Pattern;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
@ -56,7 +58,11 @@ public class GraalTutorial extends InvokeGraal {
byte[] bytecodes = bytecode.getCode();
Assert.assertNotNull(bytecodes);
System.out.println(new BytecodeDisassembler().disassemble(bytecode));
Pattern disassemblyLineRE = Pattern.compile(" *\\d+: [a-z][\\w_]+");
String disassembly = new BytecodeDisassembler().disassemble(bytecode);
for (String line : disassembly.split("\\n")) {
Assert.assertTrue(line, disassemblyLineRE.matcher(line).find());
}
}
/*

View File

@ -39,6 +39,7 @@ import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugCounter;
import org.graalvm.compiler.debug.DebugTimer;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.MethodFilter;
import org.graalvm.compiler.debug.internal.method.MethodMetricsRootScopeInfo;
import org.graalvm.compiler.lir.LIR;
import org.graalvm.compiler.lir.alloc.OutOfRegistersException;
@ -175,10 +176,42 @@ public class GraalCompiler {
} catch (Throwable e) {
throw Debug.handle(e);
}
checkForRequestedCrash(r.graph);
return r.compilationResult;
}
}
/**
* Checks whether the {@link GraalCompilerOptions#CrashAt} option indicates that the compilation
* of {@code graph} should result in an exception.
*
* @param graph a graph currently being compiled
* @throws RuntimeException if the value of {@link GraalCompilerOptions#CrashAt} matches
* {@code graph.method()} or {@code graph.name}
*/
private static void checkForRequestedCrash(StructuredGraph graph) {
String methodPattern = GraalCompilerOptions.CrashAt.getValue(graph.getOptions());
if (methodPattern != null) {
String crashLabel = null;
ResolvedJavaMethod method = graph.method();
if (method == null) {
if (graph.name.contains(methodPattern)) {
crashLabel = graph.name;
}
} else {
MethodFilter[] filters = MethodFilter.parse(methodPattern);
for (MethodFilter filter : filters) {
if (filter.matches(method)) {
crashLabel = method.format("%H.%n(%p)");
}
}
}
if (crashLabel != null) {
throw new RuntimeException("Forced crash after compiling " + crashLabel);
}
}
}
/**
* Builds the graph, optimizes it.
*/
@ -190,21 +223,25 @@ public class GraalCompiler {
if (graph.start().next() == null) {
graphBuilderSuite.apply(graph, highTierContext);
new DeadCodeEliminationPhase(DeadCodeEliminationPhase.Optionality.Optional).apply(graph);
Debug.dump(Debug.BASIC_LEVEL, graph, "After parsing");
} else {
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "initial state");
Debug.dump(Debug.INFO_LEVEL, graph, "initial state");
}
suites.getHighTier().apply(graph, highTierContext);
graph.maybeCompress();
Debug.dump(Debug.BASIC_LEVEL, graph, "After high tier");
MidTierContext midTierContext = new MidTierContext(providers, target, optimisticOpts, profilingInfo);
suites.getMidTier().apply(graph, midTierContext);
graph.maybeCompress();
Debug.dump(Debug.BASIC_LEVEL, graph, "After mid tier");
LowTierContext lowTierContext = new LowTierContext(providers, target);
suites.getLowTier().apply(graph, lowTierContext);
Debug.dump(Debug.BASIC_LEVEL, graph, "After low tier");
Debug.dump(Debug.BASIC_LOG_LEVEL, graph.getLastSchedule(), "Final HIR schedule");
Debug.dump(Debug.BASIC_LEVEL, graph.getLastSchedule(), "Final HIR schedule");
} catch (Throwable e) {
throw Debug.handle(e);
} finally {
@ -269,7 +306,7 @@ public class GraalCompiler {
linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock);
lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions());
Debug.dump(Debug.INFO_LOG_LEVEL, lir, "After linear scan order");
Debug.dump(Debug.INFO_LEVEL, lir, "After linear scan order");
} catch (Throwable e) {
throw Debug.handle(e);
}
@ -283,9 +320,9 @@ public class GraalCompiler {
new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context);
try (Scope s = Debug.scope("LIRStages", nodeLirGen, lir)) {
Debug.dump(Debug.BASIC_LOG_LEVEL, lir, "After LIR generation");
Debug.dump(Debug.BASIC_LEVEL, lir, "After LIR generation");
LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo));
Debug.dump(Debug.BASIC_LOG_LEVEL, lir, "Before code generation");
Debug.dump(Debug.BASIC_LEVEL, lir, "Before code generation");
return result;
} catch (Throwable e) {
throw Debug.handle(e);
@ -365,7 +402,7 @@ public class GraalCompiler {
Debug.counter("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size());
}
Debug.dump(Debug.BASIC_LOG_LEVEL, compilationResult, "After code generation");
Debug.dump(Debug.BASIC_LEVEL, compilationResult, "After code generation");
}
}
}

View File

@ -46,6 +46,8 @@ public class GraalCompilerOptions {
public static final OptionKey<Boolean> ExitVMOnException = new OptionKey<>(false);
@Option(help = "", type = OptionType.Debug)
public static final OptionKey<Boolean> PrintStackTraceOnException = new OptionKey<>(false);
@Option(help = "Pattern (see MethodFilter for format) for method that will trigger an exception when compiled. " +
"This option exists to test handling compilation crashes gracefully.", type = OptionType.Debug)
public static final OptionKey<String> CrashAt = new OptionKey<>(null);
// @formatter:on
}

View File

@ -91,12 +91,12 @@ public class GraphChangeMonitoringPhase<C extends PhaseContext> extends PhaseSui
listener = new HashSetNodeEventListener();
try (NodeEventScope s = graph.trackNodeEvents(listener)) {
try (Scope s2 = Debug.scope("WithGraphChangeMonitoring")) {
if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) {
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "*** Before phase %s", getName());
if (Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) {
Debug.dump(Debug.DETAILED_LEVEL, graph, "*** Before phase %s", getName());
}
super.run(graph, context);
if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) {
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "*** After phase %s %s", getName(), filteredNodes);
if (Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) {
Debug.dump(Debug.DETAILED_LEVEL, graph, "*** After phase %s %s", getName(), filteredNodes);
}
Debug.log("*** %s %s %s\n", message, graph, filteredNodes);
}

View File

@ -122,11 +122,41 @@ public class Debug {
return config.isDumpEnabledForMethod();
}
public static final int BASIC_LOG_LEVEL = 1;
public static final int INFO_LOG_LEVEL = 2;
public static final int VERBOSE_LOG_LEVEL = 3;
public static final int DETAILED_LOG_LEVEL = 4;
public static final int VERY_DETAILED_LOG_LEVEL = 5;
/**
* Basic debug level.
*
* For HIR dumping, only ~5 graphs per method: after parsing, after inlining, after high tier,
* after mid tier, after low tier.
*/
public static final int BASIC_LEVEL = 1;
/**
* Informational debug level.
*
* HIR dumping: One graph after each applied top-level phase.
*/
public static final int INFO_LEVEL = 2;
/**
* Verbose debug level.
*
* HIR dumping: One graph after each phase (including sub phases).
*/
public static final int VERBOSE_LEVEL = 3;
/**
* Detailed debug level.
*
* HIR dumping: Graphs within phases where interesting for a phase, max ~5 per phase.
*/
public static final int DETAILED_LEVEL = 4;
/**
* Very detailed debug level.
*
* HIR dumping: Graphs per node granularity graph change (before/after change).
*/
public static final int VERY_DETAILED_LEVEL = 5;
public static boolean isDumpEnabled(int dumpLevel) {
return ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel);
@ -183,7 +213,7 @@ public class Debug {
}
public static boolean isLogEnabled() {
return isLogEnabled(BASIC_LOG_LEVEL);
return isLogEnabled(BASIC_LEVEL);
}
public static boolean isLogEnabled(int logLevel) {
@ -420,7 +450,7 @@ public class Debug {
}
public static void log(String msg) {
log(BASIC_LOG_LEVEL, msg);
log(BASIC_LEVEL, msg);
}
/**
@ -435,7 +465,7 @@ public class Debug {
}
public static void log(String format, Object arg) {
log(BASIC_LOG_LEVEL, format, arg);
log(BASIC_LEVEL, format, arg);
}
/**
@ -451,7 +481,7 @@ public class Debug {
}
public static void log(String format, int arg) {
log(BASIC_LOG_LEVEL, format, arg);
log(BASIC_LEVEL, format, arg);
}
/**
@ -467,7 +497,7 @@ public class Debug {
}
public static void log(String format, Object arg1, Object arg2) {
log(BASIC_LOG_LEVEL, format, arg1, arg2);
log(BASIC_LEVEL, format, arg1, arg2);
}
/**
@ -480,7 +510,7 @@ public class Debug {
}
public static void log(String format, int arg1, Object arg2) {
log(BASIC_LOG_LEVEL, format, arg1, arg2);
log(BASIC_LEVEL, format, arg1, arg2);
}
/**
@ -493,7 +523,7 @@ public class Debug {
}
public static void log(String format, Object arg1, int arg2) {
log(BASIC_LOG_LEVEL, format, arg1, arg2);
log(BASIC_LEVEL, format, arg1, arg2);
}
/**
@ -506,7 +536,7 @@ public class Debug {
}
public static void log(String format, int arg1, int arg2) {
log(BASIC_LOG_LEVEL, format, arg1, arg2);
log(BASIC_LEVEL, format, arg1, arg2);
}
/**
@ -519,7 +549,7 @@ public class Debug {
}
public static void log(String format, Object arg1, Object arg2, Object arg3) {
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3);
log(BASIC_LEVEL, format, arg1, arg2, arg3);
}
/**
@ -532,7 +562,7 @@ public class Debug {
}
public static void log(String format, int arg1, int arg2, int arg3) {
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3);
log(BASIC_LEVEL, format, arg1, arg2, arg3);
}
/**
@ -545,7 +575,7 @@ public class Debug {
}
public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4) {
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4);
log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4);
}
/**
@ -558,7 +588,7 @@ public class Debug {
}
public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5);
log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5);
}
/**
@ -571,7 +601,7 @@ public class Debug {
}
public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) {
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6);
log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6);
}
/**
@ -584,11 +614,11 @@ public class Debug {
}
public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) {
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) {
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
}
/**
@ -607,7 +637,7 @@ public class Debug {
}
public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) {
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
}
public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) {
@ -617,7 +647,7 @@ public class Debug {
}
public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) {
log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
}
public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) {
@ -627,7 +657,7 @@ public class Debug {
}
public static void logv(String format, Object... args) {
logv(BASIC_LOG_LEVEL, format, args);
logv(BASIC_LEVEL, format, args);
}
/**
@ -655,7 +685,7 @@ public class Debug {
@Deprecated
public static void log(String format, Object[] args) {
assert false : "shouldn't use this";
log(BASIC_LOG_LEVEL, format, args);
log(BASIC_LEVEL, format, args);
}
/**
@ -670,6 +700,14 @@ public class Debug {
logv(logLevel, format, args);
}
/**
* Forces an unconditional dump. This method exists mainly for debugging. It can also be used to
* force a graph dump from IDEs that support invoking a Java method while at a breakpoint.
*/
public static void forceDump(Object object, String format, Object... args) {
DebugScope.forceDump(object, format, args);
}
public static void dump(int dumpLevel, Object object, String msg) {
if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) {
DebugScope.getInstance().dump(dumpLevel, object, msg);
@ -771,7 +809,7 @@ public class Debug {
}
public static Indent logAndIndent(String msg) {
return logAndIndent(BASIC_LOG_LEVEL, msg);
return logAndIndent(BASIC_LEVEL, msg);
}
/**
@ -789,7 +827,7 @@ public class Debug {
}
public static Indent logAndIndent(String format, Object arg) {
return logAndIndent(BASIC_LOG_LEVEL, format, arg);
return logAndIndent(BASIC_LEVEL, format, arg);
}
/**
@ -808,7 +846,7 @@ public class Debug {
}
public static Indent logAndIndent(String format, int arg) {
return logAndIndent(BASIC_LOG_LEVEL, format, arg);
return logAndIndent(BASIC_LEVEL, format, arg);
}
/**
@ -827,7 +865,7 @@ public class Debug {
}
public static Indent logAndIndent(String format, int arg1, Object arg2) {
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2);
return logAndIndent(BASIC_LEVEL, format, arg1, arg2);
}
/**
@ -841,7 +879,7 @@ public class Debug {
}
public static Indent logAndIndent(String format, Object arg1, int arg2) {
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2);
return logAndIndent(BASIC_LEVEL, format, arg1, arg2);
}
/**
@ -855,7 +893,7 @@ public class Debug {
}
public static Indent logAndIndent(String format, int arg1, int arg2) {
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2);
return logAndIndent(BASIC_LEVEL, format, arg1, arg2);
}
/**
@ -869,7 +907,7 @@ public class Debug {
}
public static Indent logAndIndent(String format, Object arg1, Object arg2) {
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2);
return logAndIndent(BASIC_LEVEL, format, arg1, arg2);
}
/**
@ -883,7 +921,7 @@ public class Debug {
}
public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3) {
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3);
return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3);
}
/**
@ -897,7 +935,7 @@ public class Debug {
}
public static Indent logAndIndent(String format, int arg1, int arg2, int arg3) {
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3);
return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3);
}
/**
@ -911,7 +949,7 @@ public class Debug {
}
public static Indent logAndIndent(String format, Object arg1, int arg2, int arg3) {
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3);
return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3);
}
/**
@ -925,7 +963,7 @@ public class Debug {
}
public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4) {
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4);
return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4);
}
/**
@ -939,7 +977,7 @@ public class Debug {
}
public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5);
return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5);
}
/**
@ -953,7 +991,7 @@ public class Debug {
}
public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) {
return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6);
return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6);
}
/**
@ -1001,7 +1039,7 @@ public class Debug {
@Deprecated
public static void logAndIndent(String format, Object[] args) {
assert false : "shouldn't use this";
logAndIndent(BASIC_LOG_LEVEL, format, args);
logAndIndent(BASIC_LEVEL, format, args);
}
/**

View File

@ -41,28 +41,28 @@ import org.graalvm.compiler.debug.internal.DebugScope;
* A filter is a list of comma-separated terms of the form {@code <pattern>[:<level>]}. {@code
* <pattern>} is interpreted as a glob pattern if it contains a "*" or "?" character. Otherwise, it
* is interpreted as a substring. If {@code <pattern>} is empty, it matches every scope. If {@code :
* <level>} is omitted, it defaults to {@link Debug#BASIC_LOG_LEVEL}. The term {@code ~<pattern>} is
* a shorthand for {@code <pattern>:0} to disable a debug facility for a pattern.
* <level>} is omitted, it defaults to {@link Debug#BASIC_LEVEL}. The term {@code ~<pattern>} is a
* shorthand for {@code <pattern>:0} to disable a debug facility for a pattern.
* <p>
* The resulting log level of a scope is determined by the <em>last</em> matching term. If no term
* matches, the log level is 0 (disabled). A filter with no terms matches every scope with a log
* level of {@link Debug#BASIC_LOG_LEVEL}.
* level of {@link Debug#BASIC_LEVEL}.
*
* <h2>Examples of filters</h2>
*
* <ul>
* <li>(empty string)<br>
* Matches any scope with log level {@link Debug#BASIC_LOG_LEVEL}.
* Matches any scope with log level {@link Debug#BASIC_LEVEL}.
*
* <li>{@code :1}<br>
* Matches any scope with log level 1.
*
* <li>{@code *}<br>
* Matches any scope with log level {@link Debug#BASIC_LOG_LEVEL}.
* Matches any scope with log level {@link Debug#BASIC_LEVEL}.
*
* <li>{@code CodeGen,CodeInstall}<br>
* Matches scopes containing "CodeGen" or "CodeInstall", both with log level
* {@link Debug#BASIC_LOG_LEVEL}.
* {@link Debug#BASIC_LEVEL}.
*
* <li>{@code CodeGen:2,CodeInstall:1}<br>
* Matches scopes containing "CodeGen" with log level 2, or "CodeInstall" with log level 1.
@ -74,10 +74,10 @@ import org.graalvm.compiler.debug.internal.DebugScope;
* Matches all scopes with log level 1, except those containing "Dead".
*
* <li>{@code Code*}<br>
* Matches scopes starting with "Code" with log level {@link Debug#BASIC_LOG_LEVEL}.
* Matches scopes starting with "Code" with log level {@link Debug#BASIC_LEVEL}.
*
* <li>{@code Code,~Dead}<br>
* Matches scopes containing "Code" but not "Dead", with log level {@link Debug#BASIC_LOG_LEVEL}.
* Matches scopes containing "Code" but not "Dead", with log level {@link Debug#BASIC_LEVEL}.
* </ul>
*/
final class DebugFilter {
@ -108,7 +108,7 @@ final class DebugFilter {
level = 0;
} else {
pattern = t;
level = Debug.BASIC_LOG_LEVEL;
level = Debug.BASIC_LEVEL;
}
} else {
pattern = t.substring(0, idx);
@ -119,13 +119,13 @@ final class DebugFilter {
} catch (NumberFormatException e) {
switch (levelString) {
case "basic":
level = Debug.BASIC_LOG_LEVEL;
level = Debug.BASIC_LEVEL;
break;
case "info":
level = Debug.INFO_LOG_LEVEL;
level = Debug.INFO_LEVEL;
break;
case "verbose":
level = Debug.VERBOSE_LOG_LEVEL;
level = Debug.VERBOSE_LEVEL;
break;
default:
throw new IllegalArgumentException("Unknown dump level: \"" + levelString + "\" expected basic, info, verbose or an integer");
@ -133,7 +133,7 @@ final class DebugFilter {
}
} else {
level = Debug.BASIC_LOG_LEVEL;
level = Debug.BASIC_LEVEL;
}
}
@ -147,7 +147,7 @@ final class DebugFilter {
*/
public int matchLevel(String input) {
if (terms == null) {
return Debug.BASIC_LOG_LEVEL;
return Debug.BASIC_LEVEL;
} else {
int level = 0;
for (Term t : terms) {

View File

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

View File

@ -79,7 +79,9 @@ public class GraalDebugConfig implements DebugConfig {
@Option(help = "Write debug values into a file instead of the terminal. " +
"If DebugValueSummary is Thread, the thread name will be prepended.", type = OptionType.Debug)
public static final OptionKey<String> DebugValueFile = new OptionKey<>(null);
@Option(help = "Send Graal compiler IR to dump handlers on error", type = OptionType.Debug)
@Option(help = "Enable debug output for stub code generation and snippet preparation.", type = OptionType.Debug)
public static final OptionKey<Boolean> DebugStubsAndSnippets = new OptionKey<>(false);
@Option(help = "Send Graal compiler IR to dump handlers on error.", type = OptionType.Debug)
public static final OptionKey<Boolean> DumpOnError = new OptionKey<>(false);
@Option(help = "Intercept also bailout exceptions", type = OptionType.Debug)
public static final OptionKey<Boolean> InterceptBailout = new OptionKey<>(false);
@ -406,7 +408,7 @@ public class GraalDebugConfig implements DebugConfig {
if (e instanceof BailoutException && !Options.InterceptBailout.getValue(options)) {
return null;
}
Debug.setConfig(Debug.fixedConfig(options, Debug.BASIC_LOG_LEVEL, Debug.BASIC_LOG_LEVEL, false, false, false, false, false, dumpHandlers, verifyHandlers, output));
Debug.setConfig(Debug.fixedConfig(options, Debug.BASIC_LEVEL, Debug.BASIC_LEVEL, false, false, false, false, false, dumpHandlers, verifyHandlers, output));
Debug.log("Exception occurred in scope: %s", Debug.currentScope());
Map<Object, Object> firstSeen = new IdentityHashMap<>();
for (Object o : Debug.context()) {
@ -414,7 +416,7 @@ public class GraalDebugConfig implements DebugConfig {
if (!firstSeen.containsKey(o)) {
firstSeen.put(o, o);
if (Options.DumpOnError.getValue(options) || Options.Dump.getValue(options) != null) {
Debug.dump(Debug.BASIC_LOG_LEVEL, o, "Exception: %s", e);
Debug.dump(Debug.BASIC_LEVEL, o, "Exception: %s", e);
} else {
Debug.log("Context obj %s", o);
}

View File

@ -352,7 +352,7 @@ public final class DebugScope implements Debug.Scope {
dumpHandler.dump(object, message);
}
} else {
TTY.println("Forced dump ignored because debugging is disabled - use -Dgraal.Dump=xxx");
TTY.println("Forced dump ignored because debugging is disabled - use -Dgraal.ForceDebugEnable=true");
}
}

View File

@ -405,6 +405,13 @@ public class Graph {
return add(node);
}
public <T extends Node> T maybeAddOrUnique(T node) {
if (node.isAlive()) {
return node;
}
return addOrUnique(node);
}
public <T extends Node> T addOrUniqueWithInputs(T node) {
if (node.isAlive()) {
assert node.graph() == this;

View File

@ -40,6 +40,8 @@ import java.util.Objects;
import java.util.function.Predicate;
import org.graalvm.compiler.core.common.Fields;
import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.Fingerprint;
import org.graalvm.compiler.graph.Graph.NodeEvent;
@ -131,7 +133,9 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
* Denotes an injected parameter in a {@linkplain NodeIntrinsic node intrinsic} constructor. If
* the constructor is called as part of node intrinsification, the node intrinsifier will inject
* an argument for the annotated parameter. Injected parameters must precede all non-injected
* parameters in a constructor.
* parameters in a constructor. If the type of the annotated parameter is {@link Stamp}, the
* {@linkplain Stamp#javaType type} of the injected stamp is the return type of the annotated
* method (which cannot be {@code void}).
*/
@java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(ElementType.PARAMETER)
@ -140,40 +144,45 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
/**
* Annotates a method that can be replaced by a compiler intrinsic. A (resolved) call to the
* annotated method can be replaced with an instance of the node class denoted by
* {@link #value()}. For this reason, the signature of the annotated method must match the
* signature (excluding a prefix of {@linkplain InjectedNodeParameter injected} parameters) of a
* constructor in the node class.
* annotated method will be processed by a generated {@code InvocationPlugin} that calls either
* a factory method or a constructor corresponding with the annotated method.
* <p>
* If the node class has a static method {@code intrinsify} with a matching signature plus a
* {@code GraphBuilderContext} as first argument, this method is called instead of creating the
* node.
* A factory method corresponding to an annotated method is a static method named
* {@code intrinsify} defined in the class denoted by {@link #value()}. In order, its signature
* is as follows:
* <ol>
* <li>A {@code GraphBuilderContext} parameter.</li>
* <li>A {@code ResolvedJavaMethod} parameter.</li>
* <li>A sequence of zero or more {@linkplain InjectedNodeParameter injected} parameters.</li>
* <li>Remaining parameters that match the declared parameters of the annotated method.</li>
* </ol>
* A constructor corresponding to an annotated method is defined in the class denoted by
* {@link #value()}. In order, its signature is as follows:
* <ol>
* <li>A sequence of zero or more {@linkplain InjectedNodeParameter injected} parameters.</li>
* <li>Remaining parameters that match the declared parameters of the annotated method.</li>
* </ol>
* There must be exactly one such factory method or constructor corresponding to a
* {@link NodeIntrinsic} annotated method.
*/
@java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(ElementType.METHOD)
public static @interface NodeIntrinsic {
/**
* Gets the {@link Node} subclass instantiated when intrinsifying a call to the annotated
* method. If not specified, then the class in which the annotated method is declared is
* used (and is assumed to be a {@link Node} subclass).
* The class declaring the factory method or {@link Node} subclass declaring the constructor
* used to intrinsify a call to the annotated method. The default value is the class in
* which the annotated method is declared.
*/
Class<?> value() default NodeIntrinsic.class;
/**
* Determines if the stamp of the instantiated intrinsic node has its stamp set from the
* return type of the annotated method.
* <p>
* When it is set to true, the stamp that is passed in to the constructor of ValueNode is
* ignored and can therefore safely be {@code null}.
* If {@code true}, the factory method or constructor selected by the annotation must have
* an {@linkplain InjectedNodeParameter injected} {@link Stamp} parameter. Calling
* {@link AbstractPointerStamp#nonNull()} on the injected stamp is guaranteed to return
* {@code true}.
*/
boolean setStampFromReturnType() default false;
/**
* Determines if the stamp of the instantiated intrinsic node is guaranteed to be non-null.
* Generally used in conjunction with {@link #setStampFromReturnType()}.
*/
boolean returnStampIsNonNull() default false;
boolean injectedStampIsNonNull() default false;
}
/**
@ -304,7 +313,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
* @return an {@link NodeIterable iterable} for all non-null successor edges.
*/
public NodeIterable<Node> successors() {
assert !this.isDeleted();
assert !this.isDeleted() : this;
return nodeClass.getSuccessorIterable(this);
}
@ -328,7 +337,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
if (usage1 == null) {
return 1;
}
return 2 + extraUsagesCount;
return INLINE_USAGE_COUNT + extraUsagesCount;
}
/**
@ -391,30 +400,45 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
}
private void movUsageFromEndTo(int destIndex) {
int lastIndex = this.getUsageCount() - 1;
if (destIndex == 0) {
if (lastIndex == 0) {
usage0 = null;
return;
} else if (lastIndex == 1) {
if (destIndex >= INLINE_USAGE_COUNT) {
movUsageFromEndToExtraUsages(destIndex - INLINE_USAGE_COUNT);
} else if (destIndex == 1) {
movUsageFromEndToIndexOne();
} else {
assert destIndex == 0;
movUsageFromEndToIndexZero();
}
}
private void movUsageFromEndToExtraUsages(int destExtraIndex) {
this.extraUsagesCount--;
Node n = extraUsages[extraUsagesCount];
extraUsages[destExtraIndex] = n;
extraUsages[extraUsagesCount] = null;
}
private void movUsageFromEndToIndexZero() {
if (extraUsagesCount > 0) {
this.extraUsagesCount--;
usage0 = extraUsages[extraUsagesCount];
extraUsages[extraUsagesCount] = null;
} else if (usage1 != null) {
usage0 = usage1;
usage1 = null;
return;
} else {
usage0 = extraUsages[lastIndex - INLINE_USAGE_COUNT];
usage0 = null;
}
} else if (destIndex == 1) {
if (lastIndex == 1) {
usage1 = null;
return;
}
usage1 = extraUsages[lastIndex - INLINE_USAGE_COUNT];
} else {
Node n = extraUsages[lastIndex - INLINE_USAGE_COUNT];
extraUsages[destIndex - INLINE_USAGE_COUNT] = n;
}
extraUsages[lastIndex - INLINE_USAGE_COUNT] = null;
private void movUsageFromEndToIndexOne() {
if (extraUsagesCount > 0) {
this.extraUsagesCount--;
usage1 = extraUsages[extraUsagesCount];
extraUsages[extraUsagesCount] = null;
} else {
assert usage1 != null;
usage1 = null;
}
}
/**
@ -425,20 +449,21 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
*/
public boolean removeUsage(Node node) {
assert node != null;
// It is critical that this method maintains the invariant that
// the usage list has no null element preceding a non-null element
// For large graphs, usage removal is performance critical.
// Furthermore, it is critical that this method maintains the invariant that the usage list
// has no null element preceding a non-null element.
incUsageModCount();
if (usage0 == node) {
this.movUsageFromEndTo(0);
movUsageFromEndToIndexZero();
return true;
}
if (usage1 == node) {
this.movUsageFromEndTo(1);
movUsageFromEndToIndexOne();
return true;
}
for (int i = this.extraUsagesCount - 1; i >= 0; i--) {
if (extraUsages[i] == node) {
this.movUsageFromEndTo(i + INLINE_USAGE_COUNT);
movUsageFromEndToExtraUsages(i);
return true;
}
}
@ -537,8 +562,9 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
assert assertTrue(id == INITIAL_ID, "unexpected id: %d", id);
this.graph = newGraph;
newGraph.register(this);
this.getNodeClass().registerAtInputsAsUsage(this);
this.getNodeClass().registerAtSuccessorsAsPredecessor(this);
NodeClass<? extends Node> nc = nodeClass;
nc.registerAtInputsAsUsage(this);
nc.registerAtSuccessorsAsPredecessor(this);
}
/**
@ -588,7 +614,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
}
public final void replaceAtUsages(Node other) {
replaceAtUsages(other, null, null);
replaceAtAllUsages(other, (Node) null);
}
public final void replaceAtUsages(Node other, Predicate<Node> filter) {
@ -606,11 +632,39 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
}
protected void replaceAtUsages(Node other, Predicate<Node> filter, Node toBeDeleted) {
if (filter == null) {
replaceAtAllUsages(other, toBeDeleted);
} else {
replaceAtMatchingUsages(other, filter, toBeDeleted);
}
}
protected void replaceAtAllUsages(Node other, Node toBeDeleted) {
assert checkReplaceWith(other);
int i = 0;
while (i < this.getUsageCount()) {
Node usage = this.getUsageAt(i);
if (filter == null || filter.test(usage)) {
if (usage0 == null) {
return;
}
replaceAtUsage(other, toBeDeleted, usage0);
usage0 = null;
if (usage1 == null) {
return;
}
replaceAtUsage(other, toBeDeleted, usage1);
usage1 = null;
if (extraUsagesCount <= 0) {
return;
}
for (int i = 0; i < extraUsagesCount; i++) {
Node usage = extraUsages[i];
replaceAtUsage(other, toBeDeleted, usage);
}
this.extraUsages = NO_NODES;
this.extraUsagesCount = 0;
}
private void replaceAtUsage(Node other, Node toBeDeleted, Node usage) {
boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other);
assert assertTrue(result, "not found in inputs, usage: %s", usage);
/*
@ -622,6 +676,16 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
if (other != null) {
other.addUsage(usage);
}
}
private void replaceAtMatchingUsages(Node other, Predicate<Node> filter, Node toBeDeleted) {
assert filter != null;
assert checkReplaceWith(other);
int i = 0;
while (i < this.getUsageCount()) {
Node usage = this.getUsageAt(i);
if (filter == null || filter.test(usage)) {
replaceAtUsage(other, toBeDeleted, usage);
this.movUsageFromEndTo(i);
} else {
++i;
@ -641,21 +705,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
public void replaceAtMatchingUsages(Node other, NodePredicate usagePredicate) {
assert checkReplaceWith(other);
int index = 0;
while (index < this.getUsageCount()) {
Node usage = getUsageAt(index);
if (usagePredicate.apply(usage)) {
boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other);
assert assertTrue(result, "not found in inputs, usage: %s", usage);
if (other != null) {
maybeNotifyInputChanged(usage);
other.addUsage(usage);
}
this.movUsageFromEndTo(index);
} else {
index++;
}
}
replaceAtMatchingUsages(other, usagePredicate, null);
}
public void replaceAtUsages(InputType type, Node other) {

View File

@ -154,7 +154,7 @@ public final class NodeBitMap implements NodeIterable<Node> {
if (bits.length < other.bits.length) {
bits = Arrays.copyOf(bits, other.bits.length);
}
for (int i = 0; i < bits.length; i++) {
for (int i = 0; i < Math.min(bits.length, other.bits.length); i++) {
bits[i] |= other.bits[i];
}
}
@ -181,44 +181,47 @@ public final class NodeBitMap implements NodeIterable<Node> {
}
}
private static class MarkedNodeIterator implements Iterator<Node> {
protected int nextMarkedNodeId(int fromNodeId) {
assert fromNodeId >= 0;
int wordIndex = fromNodeId >> SHIFT;
int wordsInUse = bits.length;
if (wordIndex < wordsInUse) {
long word = bits[wordIndex] & (0xFFFFFFFFFFFFFFFFL << fromNodeId);
while (true) {
if (word != 0) {
return wordIndex * Long.SIZE + Long.numberOfTrailingZeros(word);
}
if (++wordIndex == wordsInUse) {
break;
}
word = bits[wordIndex];
}
}
return -2;
}
private final NodeBitMap visited;
private Iterator<Node> nodes;
private Node nextNode;
private class MarkedNodeIterator implements Iterator<Node> {
private int nextNodeId;
MarkedNodeIterator(NodeBitMap visited, Iterator<Node> nodes) {
this.visited = visited;
this.nodes = nodes;
MarkedNodeIterator() {
nextNodeId = -1;
forward();
}
private void forward() {
do {
if (!nodes.hasNext()) {
nextNode = null;
return;
}
nextNode = nodes.next();
if (visited.isNew(nextNode)) {
nextNode = null;
return;
}
} while (!visited.isMarked(nextNode));
nextNodeId = NodeBitMap.this.nextMarkedNodeId(nextNodeId + 1);
}
@Override
public boolean hasNext() {
return nextNode != null;
return nextNodeId >= 0;
}
@Override
public Node next() {
try {
return nextNode;
} finally {
Node result = graph.getNode(nextNodeId);
forward();
}
return result;
}
@Override
@ -230,7 +233,7 @@ public final class NodeBitMap implements NodeIterable<Node> {
@Override
public Iterator<Node> iterator() {
return new MarkedNodeIterator(NodeBitMap.this, graph().getNodes().iterator());
return new MarkedNodeIterator();
}
public NodeBitMap copy() {

View File

@ -599,23 +599,24 @@ public final class NodeClass<T> extends FieldIntrospection<T> {
}
private static boolean deepEquals0(Object e1, Object e2) {
assert e1 != null;
if (e2 == null) {
if (e1 == e2) {
return true;
} else if (e1 == null || e2 == null) {
return false;
} else if (e1 instanceof Object[] && e2 instanceof Object[]) {
return Arrays.deepEquals((Object[]) e1, (Object[]) e2);
} else if (!e1.getClass().isArray() || e1.getClass() != e2.getClass()) {
return e1.equals(e2);
} else if (e1 instanceof byte[]) {
return Arrays.equals((byte[]) e1, (byte[]) e2);
} else if (e1 instanceof short[]) {
return Arrays.equals((short[]) e1, (short[]) e2);
} else if (e1 instanceof Object[] && e2 instanceof Object[]) {
return deepEquals((Object[]) e1, (Object[]) e2);
} else if (e1 instanceof int[]) {
return Arrays.equals((int[]) e1, (int[]) e2);
} else if (e1 instanceof long[]) {
return Arrays.equals((long[]) e1, (long[]) e2);
} else if (e1 instanceof byte[]) {
return Arrays.equals((byte[]) e1, (byte[]) e2);
} else if (e1 instanceof char[]) {
return Arrays.equals((char[]) e1, (char[]) e2);
} else if (e1 instanceof short[]) {
return Arrays.equals((short[]) e1, (short[]) e2);
} else if (e1 instanceof float[]) {
return Arrays.equals((float[]) e1, (float[]) e2);
} else if (e1 instanceof double[]) {
@ -627,6 +628,20 @@ public final class NodeClass<T> extends FieldIntrospection<T> {
}
}
private static boolean deepEquals(Object[] a1, Object[] a2) {
int length = a1.length;
if (a2.length != length) {
return false;
}
for (int i = 0; i < length; i++) {
if (!deepEquals0(a1[i], a2[i])) {
return false;
}
}
return true;
}
public boolean dataEquals(Node a, Node b) {
assert a.getClass() == b.getClass();
for (int i = 0; i < data.getCount(); ++i) {

View File

@ -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() {

View File

@ -27,7 +27,7 @@ import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Queue;
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.debug.Debug;
public abstract class NodeWorkList implements Iterable<Node> {
@ -72,26 +72,19 @@ public abstract class NodeWorkList implements Iterable<Node> {
}
public static final class IterativeNodeWorkList extends NodeWorkList {
private static final int HARD_ITERATION_LIMIT = 1_000_000;
private static final int EXPLICIT_BITMAP_THRESHOLD = 10;
protected NodeBitMap inQueue;
private int iterationLimit;
private boolean hardLimit;
private Node firstNoChange;
private Node lastPull;
private Node lastChain;
public IterativeNodeWorkList(Graph graph, boolean fill, int iterationLimitPerNode) {
super(graph, fill);
if (iterationLimitPerNode > 0) {
assert iterationLimitPerNode > 0;
long limit = (long) iterationLimitPerNode * graph.getNodeCount();
iterationLimit = (int) Long.min(Integer.MAX_VALUE, limit);
hardLimit = false;
} else {
iterationLimit = HARD_ITERATION_LIMIT;
hardLimit = true;
}
}
@Override
@ -101,12 +94,9 @@ public abstract class NodeWorkList implements Iterable<Node> {
public boolean hasNext() {
dropDeleted();
if (iterationLimit <= 0) {
if (hardLimit) {
throw new PermanentBailoutException("Iteration limit reached");
} else {
Debug.log(Debug.INFO_LEVEL, "Exceeded iteration limit in IterativeNodeWorkList");
return false;
}
}
return !worklist.isEmpty();
}
@ -152,7 +142,7 @@ public abstract class NodeWorkList implements Iterable<Node> {
}
}
}
assert checkInfiniteWork(node) : "Readded " + node;
assert checkInfiniteWork(node) : "Re-added " + node;
if (inQueue != null) {
inQueue.markAndGrow(node);
}

View File

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

View File

@ -105,6 +105,7 @@ public abstract class NodePredicates {
return !a.apply(n);
}
@Override
public NodePredicate negate() {
return a;
}
@ -148,6 +149,7 @@ public abstract class NodePredicates {
return this;
}
@Override
public NodePredicate negate() {
return new NegativeTypePredicate(this);
}
@ -183,6 +185,7 @@ public abstract class NodePredicates {
return this;
}
@Override
public NodePredicate negate() {
return new PositiveTypePredicate(this);
}

View File

@ -557,7 +557,7 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp
LIR lir = getResult().getLIR();
ArrayList<LIRInstruction> instructions = lir.getLIRforBlock(lir.getControlFlowGraph().getStartBlock());
instructions.add(1, op);
Debug.dump(Debug.INFO_LOG_LEVEL, lir, "created rescue dummy op");
Debug.dump(Debug.INFO_LEVEL, lir, "created rescue dummy op");
}
}

View File

@ -48,7 +48,7 @@ public class ClassSubstitutionsTests extends GraalCompilerTest {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
compile(graph.method(), graph);
assertNotInGraph(graph, Invoke.class);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet);
Debug.dump(Debug.BASIC_LEVEL, graph, snippet);
return graph;
} catch (Throwable e) {
throw Debug.handle(e);

View File

@ -47,7 +47,7 @@ public class CompileTheWorldTest extends GraalCompilerTest {
System.setProperty(CompileTheWorld.LIMITMODS_PROPERTY_NAME, "java.base");
OptionValues initialOptions = getInitialOptions();
EconomicMap<OptionKey<?>, Object> compilationOptions = CompileTheWorld.parseOptions("Inline=false");
new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, true, initialOptions, compilationOptions).compile();
new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, false, initialOptions, compilationOptions).compile();
assert ExitVMOnException.getValue(initialOptions) == originalSetting;
}
}

View File

@ -57,7 +57,7 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
compile(graph.method(), graph);
assertNotInGraph(graph, Invoke.class);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet);
Debug.dump(Debug.BASIC_LEVEL, graph, snippet);
return graph;
} catch (Throwable e) {
throw Debug.handle(e);
@ -117,59 +117,32 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest {
}
}
/**
* Disables these tests until we know how to dynamically export the {@code jdk.internal.reflect}
* package from the {@code java.base} module to the unnamed module associated with
* {@link AsmLoader}. Without such an export, the test fails as follows:
*
* <pre>
* Caused by: java.lang.IllegalAccessError: class org.graalvm.compiler.hotspot.test.ConstantPoolTest
* (in unnamed module @0x57599b23) cannot access class jdk.internal.reflect.ConstantPool (in
* module java.base) because module java.base does not export jdk.internal.reflect to unnamed
* module @0x57599b23
* </pre>
*/
private static void assumeJDK8() {
// Assume.assumeTrue(Java8OrEarlier);
}
@Test
public void testGetSize() {
assumeJDK8();
Object cp = getConstantPoolForObject();
test("getSize", cp);
}
@Test
public void testGetIntAt() {
assumeJDK8();
test("getIntAt");
}
@Test
public void testGetLongAt() {
assumeJDK8();
test("getLongAt");
}
@Test
public void testGetFloatAt() {
assumeJDK8();
test("getFloatAt");
}
@Test
public void testGetDoubleAt() {
assumeJDK8();
test("getDoubleAt");
}
// @Test
public void testGetUTF8At() {
assumeJDK8();
test("getUTF8At");
}
private static final String PACKAGE_NAME = ConstantPoolSubstitutionsTests.class.getPackage().getName();
private static final String PACKAGE_NAME_INTERNAL = PACKAGE_NAME.replace('.', '/');

View File

@ -53,6 +53,7 @@ import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.VirtualObject;
import jdk.vm.ci.code.site.InfopointReason;
import jdk.vm.ci.common.JVMCIError;
@ -140,8 +141,9 @@ public class JVMCIInfopointErrorTest extends GraalCompilerTest {
graph.addAfterFixed(graph.start(), test);
CompilationResult compResult = compile(method, graph);
HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(method, null, compResult);
getCodeCache().addCode(method, compiledCode, null, null);
CodeCacheProvider codeCache = getCodeCache();
HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, method, null, compResult);
codeCache.addCode(method, compiledCode, null, null);
}
@Test(expected = JVMCIError.class)

View File

@ -58,7 +58,11 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest {
@Override
@SuppressWarnings("try")
protected Suites createSuites(OptionValues options) {
return super.createSuites(new OptionValues(options, GraalOptions.ImmutableCode, true));
return super.createSuites(getOptions());
}
private static OptionValues getOptions() {
return new OptionValues(getInitialOptions(), GraalOptions.ImmutableCode, true);
}
@Override
@ -77,7 +81,7 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest {
@Test
public void testClassConstant() {
test("classConstant");
test(getOptions(), "classConstant");
}
public static Class<?> primitiveClassConstant() {
@ -86,7 +90,7 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest {
@Test
public void testPrimitiveClassConstant() {
test("primitiveClassConstant");
test(getOptions(), "primitiveClassConstant");
}
public static Wrapper compressedClassConstant(Wrapper w) {
@ -97,7 +101,7 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest {
@Test
public void testCompressedClassConstant() {
ArgSupplier arg = () -> new Wrapper();
test("compressedClassConstant", arg);
test(getOptions(), "compressedClassConstant", arg);
}
public static Wrapper compressedPrimitiveClassConstant(Wrapper w) {
@ -108,6 +112,6 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest {
@Test
public void testCompressedPrimitiveClassConstant() {
ArgSupplier arg = () -> new Wrapper();
test("compressedPrimitiveClassConstant", arg);
test(getOptions(), "compressedPrimitiveClassConstant", arg);
}
}

View File

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

View File

@ -266,7 +266,7 @@ public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest {
new GuardLoweringPhase().apply(graph, midContext);
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext);
new WriteBarrierAdditionPhase(config).apply(graph);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After Write Barrier Addition");
Debug.dump(Debug.BASIC_LEVEL, graph, "After Write Barrier Addition");
int barriers = 0;
if (config.useG1GC) {

View File

@ -30,7 +30,20 @@ import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation;
import static org.graalvm.compiler.core.GraalCompilerOptions.PrintFilter;
import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException;
import static org.graalvm.compiler.core.phases.HighTier.Options.Inline;
import static org.graalvm.compiler.debug.Debug.INFO_LEVEL;
import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.DUMP_METHOD;
import static org.graalvm.compiler.debug.DelegatingDebugConfig.Level.DUMP;
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump;
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DumpPath;
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.ForceDebugEnable;
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintCFGFileName;
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintGraphFile;
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintGraphFileName;
import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.graalvm.compiler.code.CompilationResult;
@ -38,7 +51,9 @@ import org.graalvm.compiler.debug.Debug;
import org.graalvm.compiler.debug.Debug.Scope;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugCounter;
import org.graalvm.compiler.debug.DebugDumpHandler;
import org.graalvm.compiler.debug.DebugDumpScope;
import org.graalvm.compiler.debug.DebugRetryableTask;
import org.graalvm.compiler.debug.DebugTimer;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.Management;
@ -46,6 +61,7 @@ import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.debug.TimeSource;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.printer.GraalDebugConfigCustomizer;
import org.graalvm.util.EconomicMap;
import jdk.vm.ci.code.BailoutException;
@ -96,6 +112,136 @@ public class CompilationTask {
private final boolean useProfilingInfo;
private final OptionValues options;
final class RetryableCompilation extends DebugRetryableTask<HotSpotCompilationRequestResult> {
private final EventProvider.CompilationEvent compilationEvent;
CompilationResult result;
RetryableCompilation(EventProvider.CompilationEvent compilationEvent) {
this.compilationEvent = compilationEvent;
}
@SuppressWarnings("try")
@Override
protected HotSpotCompilationRequestResult run(Throwable retryCause) {
HotSpotResolvedJavaMethod method = getMethod();
int entryBCI = getEntryBCI();
final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR);
final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed();
final boolean printAfterCompilation = PrintAfterCompilation.getValue(options) && !TTY.isSuppressed();
if (printCompilation) {
TTY.println(getMethodDescription() + "...");
}
TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(options), method);
final long start;
final long allocatedBytesBefore;
if (printAfterCompilation || printCompilation) {
final long threadId = Thread.currentThread().getId();
start = TimeSource.getTimeNS();
allocatedBytesBefore = printAfterCompilation || printCompilation ? Lazy.threadMXBean.getThreadAllocatedBytes(threadId) : 0L;
} else {
start = 0L;
allocatedBytesBefore = 0L;
}
try (Scope s = Debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) {
// Begin the compilation event.
compilationEvent.begin();
result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options);
} catch (Throwable e) {
throw Debug.handle(e);
} finally {
// End the compilation event.
compilationEvent.end();
filter.remove();
if (printAfterCompilation || printCompilation) {
final long threadId = Thread.currentThread().getId();
final long stop = TimeSource.getTimeNS();
final long duration = (stop - start) / 1000000;
final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1;
final int bytecodeSize = result != null ? result.getBytecodeSize() : 0;
final long allocatedBytesAfter = Lazy.threadMXBean.getThreadAllocatedBytes(threadId);
final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024;
if (printAfterCompilation) {
TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes));
} else if (printCompilation) {
TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dB %5dkB", getId(), "", "", "", duration, bytecodeSize, targetCodeSize, allocatedKBytes));
}
}
}
if (result != null) {
try (DebugCloseable b = CodeInstallationTime.start()) {
installMethod(result);
}
}
stats.finish(method, installedCode);
if (result != null) {
return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize());
}
return null;
}
@Override
protected boolean onRetry(Throwable t) {
if (t instanceof BailoutException) {
return false;
}
if (!Debug.isEnabled()) {
TTY.printf("Error while processing %s.%nRe-run with -D%s%s=true to capture graph dumps upon a compilation failure.%n", CompilationTask.this,
HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX, ForceDebugEnable.getName());
return false;
}
if (Dump.hasBeenSet(options)) {
// If dumping is explicitly enabled, Graal is being debugged
// so don't interfere with what the user is expecting to see.
return false;
}
String outputDirectory = compiler.getGraalRuntime().getOutputDirectory();
if (outputDirectory == null) {
return false;
}
String methodFQN = getMethod().format("%H.%n");
File dumpPath = new File(outputDirectory, methodFQN);
dumpPath.mkdirs();
if (!dumpPath.exists()) {
TTY.println("Warning: could not create dump directory " + dumpPath);
return false;
}
TTY.println("Retrying " + CompilationTask.this);
retryDumpHandlers = new ArrayList<>();
retryOptions = new OptionValues(options,
PrintGraphFile, true,
PrintCFGFileName, methodFQN,
PrintGraphFileName, methodFQN,
DumpPath, dumpPath.getPath());
override(DUMP, INFO_LEVEL).enable(DUMP_METHOD);
new GraalDebugConfigCustomizer().customize(this);
return true;
}
private Collection<DebugDumpHandler> retryDumpHandlers;
private OptionValues retryOptions;
@Override
public Collection<DebugDumpHandler> dumpHandlers() {
return retryDumpHandlers;
}
@Override
public OptionValues getOptions() {
return retryOptions;
}
}
static class Lazy {
/**
* A {@link com.sun.management.ThreadMXBean} to be able to query some information about the
@ -196,9 +342,8 @@ public class CompilationTask {
public HotSpotCompilationRequestResult runCompilation() {
HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime();
GraalHotSpotVMConfig config = graalRuntime.getVMConfig();
final long threadId = Thread.currentThread().getId();
int entryBCI = getEntryBCI();
final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
HotSpotResolvedJavaMethod method = getMethod();
// register the compilation id in the method metrics
@ -220,64 +365,9 @@ public class CompilationTask {
return null;
}
CompilationResult result = null;
RetryableCompilation compilation = new RetryableCompilation(compilationEvent);
try (DebugCloseable a = CompilationTime.start()) {
CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR);
final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed();
final boolean printAfterCompilation = PrintAfterCompilation.getValue(options) && !TTY.isSuppressed();
if (printCompilation) {
TTY.println(getMethodDescription() + "...");
}
TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(options), method);
final long start;
final long allocatedBytesBefore;
if (printAfterCompilation || printCompilation) {
start = TimeSource.getTimeNS();
allocatedBytesBefore = printAfterCompilation || printCompilation ? Lazy.threadMXBean.getThreadAllocatedBytes(threadId) : 0L;
} else {
start = 0L;
allocatedBytesBefore = 0L;
}
try (Scope s = Debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) {
// Begin the compilation event.
compilationEvent.begin();
result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options);
} catch (Throwable e) {
throw Debug.handle(e);
} finally {
// End the compilation event.
compilationEvent.end();
filter.remove();
if (printAfterCompilation || printCompilation) {
final long stop = TimeSource.getTimeNS();
final long duration = (stop - start) / 1000000;
final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1;
final int bytecodeSize = result != null ? result.getBytecodeSize() : 0;
final long allocatedBytesAfter = Lazy.threadMXBean.getThreadAllocatedBytes(threadId);
final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024;
if (printAfterCompilation) {
TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes));
} else if (printCompilation) {
TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dB %5dkB", getId(), "", "", "", duration, bytecodeSize, targetCodeSize, allocatedKBytes));
}
}
}
if (result != null) {
try (DebugCloseable b = CodeInstallationTime.start()) {
installMethod(result);
}
}
stats.finish(method, installedCode);
if (result != null) {
return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize());
}
return null;
return compilation.execute();
} catch (BailoutException bailout) {
BAILOUTS.increment();
if (ExitVMOnBailout.getValue(options)) {
@ -319,8 +409,9 @@ public class CompilationTask {
try {
int compiledBytecodes = 0;
int codeSize = 0;
if (result != null) {
compiledBytecodes = result.getBytecodeSize();
if (compilation.result != null) {
compiledBytecodes = compilation.result.getBytecodeSize();
CompiledBytecodes.add(compiledBytecodes);
if (installedCode != null) {
codeSize = installedCode.getSize();
@ -334,7 +425,7 @@ public class CompilationTask {
compilationEvent.setMethod(method.format("%H.%n(%p)"));
compilationEvent.setCompileId(getId());
compilationEvent.setCompileLevel(config.compilationLevelFullOptimization);
compilationEvent.setSucceeded(result != null && installedCode != null);
compilationEvent.setSucceeded(compilation.result != null && installedCode != null);
compilationEvent.setIsOsr(isOSR);
compilationEvent.setCodeSize(codeSize);
compilationEvent.setInlinedBytes(compiledBytecodes);
@ -387,7 +478,7 @@ public class CompilationTask {
installedCode = null;
Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult};
try (Scope s = Debug.scope("CodeInstall", context)) {
HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(getRequest().getMethod(), getRequest(), compResult);
HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, getRequest().getMethod(), getRequest(), compResult);
installedCode = (HotSpotInstalledCode) codeCache.installCode(getRequest().getMethod(), compiledCode, null, getRequest().getMethod().getSpeculationLog(), installAsDefault);
} catch (Throwable e) {
throw Debug.handle(e);

View File

@ -267,7 +267,31 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
public final int secondarySuperCacheOffset = getFieldOffset("Klass::_secondary_super_cache", Integer.class, "Klass*");
public final int secondarySupersOffset = getFieldOffset("Klass::_secondary_supers", Integer.class, "Array<Klass*>*");
public final int classMirrorOffset = getFieldOffset("Klass::_java_mirror", Integer.class, "oop");
public final boolean classMirrorIsHandle;
public final int classMirrorOffset;
{
String name = "Klass::_java_mirror";
int offset = -1;
boolean isHandle = false;
try {
offset = getFieldOffset(name, Integer.class, "oop");
} catch (JVMCIError e) {
}
if (offset == -1) {
try {
offset = getFieldOffset(name, Integer.class, "jobject");
isHandle = true;
} catch (JVMCIError e) {
}
}
if (offset == -1) {
throw new JVMCIError("cannot get offset of field " + name + " with type oop or jobject");
}
classMirrorOffset = offset;
classMirrorIsHandle = isHandle;
}
public final int klassSuperKlassOffset = getFieldOffset("Klass::_super", Integer.class, "Klass*");
public final int klassModifierFlagsOffset = getFieldOffset("Klass::_modifier_flags", Integer.class, "jint");

View File

@ -406,7 +406,7 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen
@Override
public CompiledCode createCompiledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compResult) {
HotSpotCompilationRequest compRequest = compilationRequest instanceof HotSpotCompilationRequest ? (HotSpotCompilationRequest) compilationRequest : null;
return HotSpotCompiledCodeBuilder.createCompiledCode(method, compRequest, compResult);
return HotSpotCompiledCodeBuilder.createCompiledCode(getCodeCache(), method, compRequest, compResult);
}
@Override

View File

@ -42,6 +42,7 @@ import org.graalvm.compiler.code.DataSection;
import org.graalvm.compiler.code.SourceMapping;
import org.graalvm.compiler.graph.NodeSourcePosition;
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.DebugInfo;
import jdk.vm.ci.code.StackSlot;
import jdk.vm.ci.code.site.ConstantReference;
@ -61,13 +62,13 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
public class HotSpotCompiledCodeBuilder {
public static HotSpotCompiledCode createCompiledCode(ResolvedJavaMethod method, HotSpotCompilationRequest compRequest, CompilationResult compResult) {
public static HotSpotCompiledCode createCompiledCode(CodeCacheProvider codeCache, ResolvedJavaMethod method, HotSpotCompilationRequest compRequest, CompilationResult compResult) {
String name = compResult.getName();
byte[] targetCode = compResult.getTargetCode();
int targetCodeSize = compResult.getTargetCodeSize();
Site[] sites = getSortedSites(compResult);
Site[] sites = getSortedSites(codeCache, compResult);
Assumption[] assumptions = compResult.getAssumptions();
@ -201,7 +202,7 @@ public class HotSpotCompiledCodeBuilder {
* {@code DebugInformationRecorder::add_new_pc_offset}). In addition, it expects
* {@link Infopoint} PCs to be unique.
*/
private static Site[] getSortedSites(CompilationResult target) {
private static Site[] getSortedSites(CodeCacheProvider codeCache, CompilationResult target) {
List<Site> sites = new ArrayList<>(
target.getExceptionHandlers().size() + target.getInfopoints().size() + target.getDataPatches().size() + target.getMarks().size() + target.getSourceMappings().size());
sites.addAll(target.getExceptionHandlers());
@ -214,10 +215,12 @@ public class HotSpotCompiledCodeBuilder {
* can really be represented and recording the end PC seems to give the best results and
* corresponds with what C1 and C2 do.
*/
if (codeCache.shouldDebugNonSafepoints()) {
for (SourceMapping source : target.getSourceMappings()) {
sites.add(new Infopoint(source.getEndOffset(), new DebugInfo(source.getSourcePosition()), InfopointReason.BYTECODE_POSITION));
assert verifySourcePositionReceivers(source.getSourcePosition());
}
}
SiteComparator c = new SiteComparator();
Collections.sort(sites, c);

View File

@ -71,8 +71,8 @@ public class HotSpotDebugInfoBuilder extends DebugInfoBuilder {
VirtualStackSlot slot = lockStack.makeLockSlot(lockDepth);
ValueNode lock = state.lockAt(lockIndex);
JavaValue object = toJavaValue(lock);
boolean eliminated = object instanceof VirtualObject || state.monitorIdAt(lockIndex) == null;
assert state.monitorIdAt(lockIndex) == null || state.monitorIdAt(lockIndex).getLockDepth() == lockDepth;
boolean eliminated = object instanceof VirtualObject || state.monitorIdAt(lockIndex).isEliminated();
assert state.monitorIdAt(lockIndex).getLockDepth() == lockDepth;
return new StackLockValue(object, slot, eliminated);
}

View File

@ -24,6 +24,7 @@ package org.graalvm.compiler.hotspot;
import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions;
import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Formattable;
@ -98,6 +99,9 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler {
@Override
@SuppressWarnings("try")
public CompilationRequestResult compileMethod(CompilationRequest request) {
if (graalRuntime.isShutdown()) {
return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), false);
}
OptionValues options = graalRuntime.getOptions();
if (graalRuntime.isBootstrapping()) {
if (GraalDebugConfig.Options.BootstrapInitializeOnly.getValue(options)) {

View File

@ -45,6 +45,7 @@ import jdk.vm.ci.services.Services;
public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFactory {
private static MethodFilter[] graalCompileOnlyFilter;
private static boolean compileGraalWithC1Only;
private final HotSpotGraalJVMCIServiceLocator locator;
@ -67,8 +68,7 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto
JVMCIVersionCheck.check(false);
assert options == null : "cannot select " + getClass() + " service more than once";
options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
initializeGraalCompileOnlyFilter(options);
if (graalCompileOnlyFilter != null || !Options.UseTrivialPrefixes.getValue(options)) {
initializeGraalCompilePolicyFields(options);
/*
* Exercise this code path early to encourage loading now. This doesn't solve problem of
* deadlock during class loading but seems to eliminate it in practice.
@ -76,9 +76,9 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto
adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization);
adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple);
}
}
private static void initializeGraalCompileOnlyFilter(OptionValues options) {
private static void initializeGraalCompilePolicyFields(OptionValues options) {
compileGraalWithC1Only = Options.CompileGraalWithC1Only.getValue(options);
String optionValue = Options.GraalCompileOnly.getValue(options);
if (optionValue != null) {
MethodFilter[] filter = MethodFilter.parse(optionValue);
@ -101,9 +101,6 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto
@Option(help = "In tiered mode compile Graal and JVMCI using optimized first tier code.", type = OptionType.Expert)
public static final OptionKey<Boolean> CompileGraalWithC1Only = new OptionKey<>(true);
@Option(help = "Hook into VM-level mechanism for denoting compilations to be performed in first tier.", type = OptionType.Expert)
public static final OptionKey<Boolean> UseTrivialPrefixes = new OptionKey<>(false);
@Option(help = "A method filter selecting what should be compiled by Graal. All other requests will be reduced to CompilationLevel.Simple.", type = OptionType.Expert)
public static final OptionKey<String> GraalCompileOnly = new OptionKey<>(null);
// @formatter:on
@ -136,29 +133,17 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto
}
}
@Override
public String[] getTrivialPrefixes() {
if (Options.UseTrivialPrefixes.getValue(options)) {
if (Options.CompileGraalWithC1Only.getValue(options)) {
return new String[]{"jdk/vm/ci", "org/graalvm/compiler", "com/oracle/graal"};
}
}
return null;
}
@Override
public CompilationLevelAdjustment getCompilationLevelAdjustment() {
if (graalCompileOnlyFilter != null) {
return CompilationLevelAdjustment.ByFullSignature;
}
if (!Options.UseTrivialPrefixes.getValue(options)) {
if (Options.CompileGraalWithC1Only.getValue(options)) {
if (compileGraalWithC1Only) {
// We only decide using the class declaring the method
// so no need to have the method name and signature
// symbols converted to a String.
return CompilationLevelAdjustment.ByHolder;
}
}
return CompilationLevelAdjustment.None;
}
@ -193,12 +178,14 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto
return CompilationLevel.Simple;
}
}
if (compileGraalWithC1Only) {
if (level.ordinal() > CompilationLevel.Simple.ordinal()) {
String declaringClassName = declaringClass.getName();
if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm.compiler") || declaringClassName.startsWith("com.oracle.graal")) {
if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm") || declaringClassName.startsWith("com.oracle.graal")) {
return CompilationLevel.Simple;
}
}
}
return level;
}
}

View File

@ -30,20 +30,28 @@ import static org.graalvm.compiler.core.common.util.Util.JAVA_SPECIFICATION_VERS
import org.graalvm.compiler.serviceprovider.ServiceProvider;
import jdk.vm.ci.hotspot.HotSpotVMEventListener;
import jdk.vm.ci.runtime.JVMCICompiler;
import jdk.vm.ci.runtime.JVMCICompilerFactory;
import jdk.vm.ci.services.JVMCIServiceLocator;
import jdk.vm.ci.services.Services;
@ServiceProvider(JVMCIServiceLocator.class)
public final class HotSpotGraalJVMCIServiceLocator extends JVMCIServiceLocator {
/**
* Holds the state shared between all {@link HotSpotGraalJVMCIServiceLocator} instances. This is
* necessary as {@link Services} can create a new instance of a service provider each time
* {@link Services#load(Class)} or {@link Services#loadSingle(Class, boolean)} is called.
*/
private static final class Shared {
static final Shared SINGLETON = new Shared();
private boolean exportsAdded;
/**
* Dynamically exports and opens various internal JDK packages to the Graal module. This
* requires only a single {@code --add-exports=java.base/jdk.internal.module=<Graal module>} on
* the VM command line instead of a {@code --add-exports} instance for each JDK internal package
* used by Graal.
* requires only a single {@code --add-exports=java.base/jdk.internal.module=<Graal module>}
* on the VM command line instead of a {@code --add-exports} instance for each JDK internal
* package used by Graal.
*/
private void addExports() {
if (JAVA_SPECIFICATION_VERSION >= 9 && !exportsAdded) {
@ -59,13 +67,10 @@ public final class HotSpotGraalJVMCIServiceLocator extends JVMCIServiceLocator {
}
}
private HotSpotGraalRuntime graalRuntime;
@Override
public <T> T getProvider(Class<T> service) {
<T> T getProvider(Class<T> service, HotSpotGraalJVMCIServiceLocator locator) {
if (service == JVMCICompilerFactory.class) {
addExports();
return service.cast(new HotSpotGraalCompilerFactory(this));
return service.cast(new HotSpotGraalCompilerFactory(locator));
} else if (service == HotSpotVMEventListener.class) {
if (graalRuntime != null) {
addExports();
@ -75,23 +80,27 @@ public final class HotSpotGraalJVMCIServiceLocator extends JVMCIServiceLocator {
return null;
}
private HotSpotGraalRuntime graalRuntime;
/**
* The signature cannot mention HotSpotGraalCompiler since it indirectly references
* JVMCICompiler which is in a non-exported JVMCI package. This causes an IllegalAccessError
* while looking for the
* <a href="http://hg.openjdk.java.net/jdk9/hs/jdk/rev/89ef4b822745#l32.65">provider</a> factory
* method:
*
* <pre>
* java.util.ServiceConfigurationError: jdk.vm.ci.services.JVMCIServiceLocator: Unable to get public provider() method
* ...
* Caused by: java.lang.IllegalAccessError: superinterface check failed: class org.graalvm.compiler.api.runtime.GraalJVMCICompiler
* (in module org.graalvm.compiler.graal_core) cannot access class jdk.vm.ci.runtime.JVMCICompiler (in module jdk.vm.ci) because
* module jdk.vm.ci does not export jdk.vm.ci.runtime to module org.graalvm.compiler.graal_core
* </pre>
* Notifies this object of the compiler created via {@link HotSpotGraalJVMCIServiceLocator}.
*/
void onCompilerCreation(JVMCICompiler compiler) {
void onCompilerCreation(HotSpotGraalCompiler compiler) {
assert this.graalRuntime == null : "only expect a single JVMCICompiler to be created";
this.graalRuntime = (HotSpotGraalRuntime) ((HotSpotGraalCompiler) compiler).getGraalRuntime();
this.graalRuntime = (HotSpotGraalRuntime) compiler.getGraalRuntime();
}
}
@Override
public <T> T getProvider(Class<T> service) {
return Shared.SINGLETON.getProvider(service, this);
}
/**
* Notifies this object of the compiler created via {@link HotSpotGraalJVMCIServiceLocator}.
*/
@SuppressWarnings("static-method")
void onCompilerCreation(HotSpotGraalCompiler compiler) {
Shared.SINGLETON.onCompilerCreation(compiler);
}
}

View File

@ -34,8 +34,22 @@ import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Log;
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodFilter;
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Verify;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.api.runtime.GraalRuntime;
@ -278,6 +292,7 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
}
private long runtimeStartTime;
private boolean shutdown;
/**
* Take action related to entering a new execution phase.
@ -291,6 +306,7 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
}
void shutdown() {
shutdown = true;
if (debugValuesPrinter != null) {
debugValuesPrinter.printDebugValues(options);
}
@ -302,6 +318,8 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
}
}
BenchmarkCounters.shutdown(runtime(), options, runtimeStartTime);
archiveAndDeleteOutputDirectory();
}
void clearMeters() {
@ -321,4 +339,95 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
public boolean isBootstrapping() {
return bootstrapJVMCI && !bootstrapFinished;
}
@Override
public boolean isShutdown() {
return shutdown;
}
/**
* Gets a unique identifier for this execution such as a process ID.
*/
private static String getExecutionID() {
String runtimeName = ManagementFactory.getRuntimeMXBean().getName();
try {
int index = runtimeName.indexOf('@');
if (index != -1) {
long pid = Long.parseLong(runtimeName.substring(0, index));
return Long.toString(pid);
}
} catch (NumberFormatException e) {
}
return runtimeName;
}
private String outputDirectory;
@Override
public String getOutputDirectory() {
if (outputDirectory == null) {
outputDirectory = "graal_output_" + getExecutionID();
File dir = new File(outputDirectory).getAbsoluteFile();
if (!dir.exists()) {
dir.mkdirs();
if (!dir.exists()) {
TTY.println("Warning: could not create Graal diagnostic directory " + dir);
return null;
}
}
}
return outputDirectory;
}
/**
* Archives and deletes the {@linkplain #getOutputDirectory() output directory} if it exists.
*/
private void archiveAndDeleteOutputDirectory() {
if (outputDirectory != null) {
Path dir = Paths.get(outputDirectory);
if (dir.toFile().exists()) {
try {
// Give compiler threads a chance to finishing dumping
Thread.sleep(1000);
} catch (InterruptedException e1) {
}
File zip = new File(outputDirectory + ".zip").getAbsoluteFile();
List<Path> toDelete = new ArrayList<>();
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip))) {
zos.setLevel(Deflater.BEST_COMPRESSION);
Files.walkFileTree(dir, Collections.emptySet(), Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (attrs.isRegularFile()) {
ZipEntry ze = new ZipEntry(file.toString());
zos.putNextEntry(ze);
zos.write(Files.readAllBytes(file));
zos.closeEntry();
}
toDelete.add(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path d, IOException exc) throws IOException {
toDelete.add(d);
return FileVisitResult.CONTINUE;
}
});
TTY.println("Graal diagnostic output saved in %s", zip);
} catch (IOException e) {
TTY.printf("IO error archiving %s:%n", dir);
e.printStackTrace(TTY.out);
}
for (Path p : toDelete) {
try {
Files.delete(p);
} catch (IOException e) {
TTY.printf("IO error deleting %s:%n", p);
e.printStackTrace(TTY.out);
}
}
}
}
}
}

View File

@ -62,4 +62,19 @@ public interface HotSpotGraalRuntimeProvider extends GraalRuntime, RuntimeProvid
* Determines if the VM is currently bootstrapping the JVMCI compiler.
*/
boolean isBootstrapping();
/**
* This runtime has been requested to shutdown.
*/
boolean isShutdown();
/**
* Gets a directory into which diagnostics such crash reports and dumps should be written. This
* method will create the directory if it doesn't exist so it should only be called if
* diagnostics are about to be generated.
*
* @return the directory into which diagnostics can be written or {@code null} if the directory
* does not exist and could not be created
*/
String getOutputDirectory();
}

View File

@ -46,10 +46,10 @@ public class HotSpotGraalVMEventListener implements HotSpotVMEventListener {
@Override
public void notifyInstall(HotSpotCodeCacheProvider codeCache, InstalledCode installedCode, CompiledCode compiledCode) {
if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) {
if (Debug.isDumpEnabled(Debug.BASIC_LEVEL)) {
CompilationResult compResult = Debug.contextLookup(CompilationResult.class);
assert compResult != null : "can't dump installed code properly without CompilationResult";
Debug.dump(Debug.BASIC_LOG_LEVEL, installedCode, "After code installation");
Debug.dump(Debug.BASIC_LEVEL, installedCode, "After code installation");
}
if (Debug.isLogEnabled()) {
Debug.log("%s", codeCache.disassemble(installedCode));

View File

@ -45,7 +45,7 @@ public class PrintStreamOptionKey extends OptionKey<String> {
}
/**
* Replace any instance of %p with a an identifying name. Try to get it from the RuntimeMXBean
* Replace any instance of %p with an identifying name. Try to get it from the RuntimeMXBean
* name.
*
* @return the name of the file to log to

View File

@ -31,6 +31,7 @@ import static org.graalvm.compiler.core.common.LocationIdentity.any;
import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_KLASS_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_HANDLE_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.COMPRESSED_HUB_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.DISPLACED_MARK_WORD_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_LOCATION;
@ -40,6 +41,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.
import java.lang.ref.Reference;
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.LocationIdentity;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
@ -409,10 +411,17 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider
return;
}
ValueNode hub = n.getHub();
GraalHotSpotVMConfig vmConfig = runtime.getVMConfig();
StructuredGraph graph = n.graph();
assert !n.getHub().isConstant();
AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getVMConfig().classMirrorOffset);
FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, n.stamp(), null, BarrierType.NONE));
assert !hub.isConstant() || GraalOptions.ImmutableCode.getValue(graph.getOptions());
AddressNode mirrorAddress = createOffsetAddress(graph, hub, vmConfig.classMirrorOffset);
FloatingReadNode read = graph.unique(new FloatingReadNode(mirrorAddress, CLASS_MIRROR_LOCATION, null, vmConfig.classMirrorIsHandle ? StampFactory.forKind(target.wordJavaKind) : n.stamp(),
null, BarrierType.NONE));
if (vmConfig.classMirrorIsHandle) {
AddressNode address = createOffsetAddress(graph, read, 0);
read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_HANDLE_LOCATION, null, n.stamp(), null, BarrierType.NONE));
}
n.replaceAtUsagesAndDelete(read);
}

View File

@ -323,7 +323,8 @@ public class HotSpotGraphBuilderPlugins {
*/
private static ValueNode getMetaspaceConstantPool(GraphBuilderContext b, ValueNode constantPoolOop, WordTypes wordTypes, GraalHotSpotVMConfig config) {
// ConstantPool.constantPoolOop is in fact the holder class.
ClassGetHubNode klass = b.add(new ClassGetHubNode(b.nullCheckedValue(constantPoolOop, DeoptimizationAction.None)));
ValueNode value = b.nullCheckedValue(constantPoolOop, DeoptimizationAction.None);
ValueNode klass = b.add(ClassGetHubNode.create(value, b.getMetaAccess(), b.getConstantReflection(), false));
boolean notCompressible = false;
AddressNode constantsAddress = b.add(new OffsetAddressNode(klass, b.add(ConstantNode.forLong(config.instanceKlassConstantsOffset))));

View File

@ -90,7 +90,7 @@ public class HotSpotSuitesProvider extends SuitesProviderBase {
if (ImmutableCode.getValue(options)) {
// lowering introduces class constants, therefore it must be after lowering
ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config.classMirrorOffset, config.useCompressedOops ? config.getOopEncoding() : null));
ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config));
if (VerifyPhases.getValue(options)) {
ret.getHighTier().appendPhase(new AheadOfTimeVerificationPhase());
}
@ -146,10 +146,10 @@ public class HotSpotSuitesProvider extends SuitesProviderBase {
protected void run(StructuredGraph graph, HighTierContext context) {
EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, runtime.getTarget().arch);
SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(context.getMetaAccess(), context.getConstantReflection(), context.getConstantFieldProvider(),
context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions()), runtime.getTarget().arch);
StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), AllowAssumptions.YES).method(graph.method()).build();
graphDecoder.decode(targetGraph, encodedGraph);
SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context.getMetaAccess(), context.getConstantReflection(),
context.getConstantFieldProvider(), context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions()));
graphDecoder.decode(encodedGraph);
}
@Override

View File

@ -109,7 +109,7 @@ class HotSpotWordOperationPlugin extends WordOperationPlugin {
PointerEqualsNode comparison = b.add(new PointerEqualsNode(left, right));
ValueNode eqValue = b.add(forBoolean(opcode == POINTER_EQ));
ValueNode neValue = b.add(forBoolean(opcode == POINTER_NE));
b.addPush(returnKind, new ConditionalNode(comparison, eqValue, neValue));
b.addPush(returnKind, ConditionalNode.create(comparison, eqValue, neValue));
break;
case IS_NULL:
@ -118,7 +118,7 @@ class HotSpotWordOperationPlugin extends WordOperationPlugin {
assert pointer.stamp() instanceof MetaspacePointerStamp;
LogicNode isNull = b.add(IsNullNode.create(pointer));
b.addPush(returnKind, new ConditionalNode(isNull, b.add(forBoolean(true)), b.add(forBoolean(false))));
b.addPush(returnKind, ConditionalNode.create(isNull, b.add(forBoolean(true)), b.add(forBoolean(false))));
break;
case FROM_POINTER:

View File

@ -29,6 +29,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
@ -72,8 +73,8 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab
* @param config
* @param markId id of the config value
*/
public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config, int markId) {
super(TYPE, StampFactory.forNodeIntrinsic());
public GraalHotSpotVMConfigNode(@InjectedNodeParameter Stamp stamp, @InjectedNodeParameter GraalHotSpotVMConfig config, int markId) {
super(TYPE, stamp);
this.config = config;
this.markId = markId;
}
@ -85,7 +86,7 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab
* @param markId id of the config value
* @param kind explicit type of the node
*/
public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config, int markId, JavaKind kind) {
public GraalHotSpotVMConfigNode(GraalHotSpotVMConfig config, int markId, JavaKind kind) {
super(TYPE, StampFactory.forKind(kind));
this.config = config;
this.markId = markId;
@ -100,13 +101,13 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab
@NodeIntrinsic
private static native boolean areConfigValuesConstant();
@NodeIntrinsic(setStampFromReturnType = true)
@NodeIntrinsic
private static native long loadLongConfigValue(@ConstantNodeParameter int markId);
@NodeIntrinsic(setStampFromReturnType = true)
@NodeIntrinsic
private static native int loadIntConfigValue(@ConstantNodeParameter int markId);
@NodeIntrinsic(setStampFromReturnType = true)
@NodeIntrinsic
private static native byte loadByteConfigValue(@ConstantNodeParameter int markId);
public static long cardTableAddress() {

View File

@ -32,7 +32,7 @@ import org.graalvm.compiler.core.common.LocationIdentity;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeInputList;
import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil;
@ -44,7 +44,6 @@ import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.Value;
/**
@ -59,8 +58,8 @@ public final class StubForeignCallNode extends FixedWithNextNode implements LIRL
protected final ForeignCallDescriptor descriptor;
public StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) {
super(TYPE, StampFactory.forKind(JavaKind.fromJavaClass(descriptor.getResultType())));
public StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, @InjectedNodeParameter Stamp stamp, ForeignCallDescriptor descriptor, ValueNode... arguments) {
super(TYPE, stamp);
this.arguments = new NodeInputList<>(this, arguments);
this.descriptor = descriptor;
this.foreignCalls = foreignCalls;

View File

@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.hotspot.nodes.aot;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
@ -44,8 +45,8 @@ public final class EncodedSymbolNode extends FloatingNode implements Canonicaliz
@OptionalInput protected ValueNode value;
public EncodedSymbolNode(ValueNode value) {
super(TYPE, null);
public EncodedSymbolNode(@InjectedNodeParameter Stamp stamp, ValueNode value) {
super(TYPE, stamp);
assert value != null;
this.value = value;
}
@ -61,6 +62,6 @@ public final class EncodedSymbolNode extends FloatingNode implements Canonicaliz
return this;
}
@NodeIntrinsic(setStampFromReturnType = true)
@NodeIntrinsic
public static native Word encode(Object constant);
}

View File

@ -22,7 +22,6 @@
*/
package org.graalvm.compiler.hotspot.phases;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_LOCATION;
import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes;
import static org.graalvm.compiler.nodes.NamedLocationIdentity.FINAL_LOCATION;
@ -32,9 +31,11 @@ import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.nodes.CompressionNode;
import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp;
import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp;
import org.graalvm.compiler.hotspot.replacements.HubGetClassNode;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
@ -67,12 +68,10 @@ import jdk.vm.ci.meta.ResolvedJavaType;
*/
public class LoadJavaMirrorWithKlassPhase extends BasePhase<PhaseContext> {
private final int classMirrorOffset;
private final CompressEncoding oopEncoding;
public LoadJavaMirrorWithKlassPhase(int classMirrorOffset, CompressEncoding oopEncoding) {
this.classMirrorOffset = classMirrorOffset;
this.oopEncoding = oopEncoding;
public LoadJavaMirrorWithKlassPhase(GraalHotSpotVMConfig config) {
this.oopEncoding = config.useCompressedOops ? config.getOopEncoding() : null;
}
private ValueNode getClassConstantReplacement(StructuredGraph graph, PhaseContext context, JavaConstant constant) {
@ -85,13 +84,12 @@ public class LoadJavaMirrorWithKlassPhase extends BasePhase<PhaseContext> {
if (type instanceof HotSpotResolvedObjectType) {
ConstantNode klass = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) type).klass(), metaAccess, graph);
AddressNode address = graph.unique(new OffsetAddressNode(klass, ConstantNode.forLong(classMirrorOffset, graph)));
ValueNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, stamp));
ValueNode getClass = graph.unique(new HubGetClassNode(metaAccess, klass));
if (((HotSpotObjectConstant) constant).isCompressed()) {
return CompressionNode.compress(read, oopEncoding);
return CompressionNode.compress(getClass, oopEncoding);
} else {
return read;
return getClass;
}
} else {
/*

View File

@ -94,7 +94,7 @@ public class OnStackReplacementPhase extends Phase {
assert graph.getNodes(EntryMarkerNode.TYPE).isEmpty();
return;
}
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement initial at bci %d", graph.getEntryBCI());
Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement initial at bci %d", graph.getEntryBCI());
EntryMarkerNode osr;
int maxIterations = -1;
@ -144,7 +144,7 @@ public class OnStackReplacementPhase extends Phase {
proxy.replaceAndDelete(proxy.value());
}
GraphUtil.removeFixedWithUnusedInputs(osr);
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement loop peeling result");
Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement loop peeling result");
} while (true);
FrameState osrState = osr.stateAfter();
@ -157,7 +157,7 @@ public class OnStackReplacementPhase extends Phase {
graph.setStart(osrStart);
osrStart.setStateAfter(osrState);
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement after setting OSR start");
Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement after setting OSR start");
final int localsSize = osrState.localsSize();
final int locksSize = osrState.locksSize();
@ -188,9 +188,9 @@ public class OnStackReplacementPhase extends Phase {
}
osr.replaceAtUsages(InputType.Guard, osrStart);
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement after replacing entry proxies");
Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement after replacing entry proxies");
GraphUtil.killCFG(start);
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement result");
Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement result");
new DeadCodeEliminationPhase(Required).apply(graph);
if (currentOSRWithLocks) {
@ -210,7 +210,7 @@ public class OnStackReplacementPhase extends Phase {
osrMonitorEnter.setNext(oldNext);
osrStart.setNext(osrMonitorEnter);
}
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "After inserting OSR monitor enters");
Debug.dump(Debug.DETAILED_LEVEL, graph, "After inserting OSR monitor enters");
/*
* Ensure balanced monitorenter - monitorexit
*
@ -226,7 +226,7 @@ public class OnStackReplacementPhase extends Phase {
}
}
}
Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement result");
Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement result");
new DeadCodeEliminationPhase(Required).apply(graph);
/*
* There must not be any parameter nodes left after OSR compilation.

View File

@ -28,9 +28,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
import jdk.vm.ci.meta.JavaConstant;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.iterators.NodeIterable;
import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
@ -43,6 +40,9 @@ import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
import jdk.vm.ci.meta.Constant;
public class EliminateRedundantInitializationPhase extends BasePhase<PhaseContext> {
/**
* Find blocks with class initializing nodes for the class identified the by the constant node.
@ -204,7 +204,7 @@ public class EliminateRedundantInitializationPhase extends BasePhase<PhaseContex
ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, true, false);
ArrayList<Node> redundantInits = new ArrayList<>();
for (ConstantNode node : getConstantNodes(graph)) {
JavaConstant constant = node.asJavaConstant();
Constant constant = node.asConstant();
if (constant instanceof HotSpotMetaspaceConstant) {
redundantInits.addAll(processConstantNode(cfg, node));
}

View File

@ -25,8 +25,11 @@ package org.graalvm.compiler.hotspot.replacements;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import org.graalvm.compiler.core.common.LocationIdentity;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.Canonicalizable;
@ -42,6 +45,7 @@ import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.extended.GetClassNode;
import org.graalvm.compiler.nodes.extended.GuardingNode;
import org.graalvm.compiler.nodes.extended.LoadHubNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import org.graalvm.compiler.nodes.memory.ReadNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.spi.Lowerable;
@ -69,19 +73,30 @@ public final class ClassGetHubNode extends FloatingNode implements Lowerable, Ca
this.clazz = clazz;
}
@Override
public Node canonical(CanonicalizerTool tool) {
if (tool.allUsagesAvailable() && hasNoUsages()) {
public static ValueNode create(ValueNode clazz, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean allUsagesAvailable) {
return canonical(null, metaAccess, constantReflection, allUsagesAvailable, KlassPointerStamp.klass(), clazz);
}
@SuppressWarnings("unused")
public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode clazz) {
ValueNode clazzValue = create(clazz, b.getMetaAccess(), b.getConstantReflection(), false);
b.push(JavaKind.Object, b.recursiveAppend(clazzValue));
return true;
}
public static ValueNode canonical(ClassGetHubNode classGetHubNode, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean allUsagesAvailable, Stamp stamp,
ValueNode clazz) {
ClassGetHubNode self = classGetHubNode;
if (allUsagesAvailable && self != null && self.hasNoUsages()) {
return null;
} else {
if (clazz.isConstant()) {
MetaAccessProvider metaAccess = tool.getMetaAccess();
if (metaAccess != null) {
ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(clazz.asJavaConstant());
ResolvedJavaType exactType = constantReflection.asJavaType(clazz.asJavaConstant());
if (exactType.isPrimitive()) {
return ConstantNode.forConstant(stamp(), JavaConstant.NULL_POINTER, metaAccess);
return ConstantNode.forConstant(stamp, JavaConstant.NULL_POINTER, metaAccess);
} else {
return ConstantNode.forConstant(stamp(), tool.getConstantReflection().asObjectHub(exactType), metaAccess);
return ConstantNode.forConstant(stamp, constantReflection.asObjectHub(exactType), metaAccess);
}
}
}
@ -90,11 +105,19 @@ public final class ClassGetHubNode extends FloatingNode implements Lowerable, Ca
return new LoadHubNode(KlassPointerStamp.klassNonNull(), getClass.getObject());
}
if (clazz instanceof HubGetClassNode) {
// replace _klass._java_mirror._klass -> _klass
// Replace: _klass._java_mirror._klass -> _klass
return ((HubGetClassNode) clazz).getHub();
}
return this;
if (self == null) {
self = new ClassGetHubNode(clazz);
}
return self;
}
}
@Override
public Node canonical(CanonicalizerTool tool) {
return canonical(this, tool.getMetaAccess(), tool.getConstantReflection(), tool.allUsagesAvailable(), stamp(), clazz);
}
@Override

View File

@ -702,17 +702,17 @@ public class HotSpotReplacementsUtil {
public static Word loadWordFromObject(Object object, int offset) {
ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
return loadWordFromObjectIntrinsic(object, offset, getWordKind(), LocationIdentity.any());
return loadWordFromObjectIntrinsic(object, offset, LocationIdentity.any(), getWordKind());
}
public static Word loadWordFromObject(Object object, int offset, LocationIdentity identity) {
ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
return loadWordFromObjectIntrinsic(object, offset, getWordKind(), identity);
return loadWordFromObjectIntrinsic(object, offset, identity, getWordKind());
}
public static KlassPointer loadKlassFromObject(Object object, int offset, LocationIdentity identity) {
ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
return loadKlassFromObjectIntrinsic(object, offset, getWordKind(), identity);
return loadKlassFromObjectIntrinsic(object, offset, identity, getWordKind());
}
/**
@ -725,17 +725,17 @@ public class HotSpotReplacementsUtil {
return registerAsWord(register, true, false);
}
@NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true)
@NodeIntrinsic(value = ReadRegisterNode.class)
public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming);
@NodeIntrinsic(value = WriteRegisterNode.class, setStampFromReturnType = true)
@NodeIntrinsic(value = WriteRegisterNode.class)
public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value);
@NodeIntrinsic(value = RawLoadNode.class, setStampFromReturnType = true)
private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity);
@NodeIntrinsic(value = RawLoadNode.class)
private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter JavaKind wordKind);
@NodeIntrinsic(value = RawLoadNode.class, setStampFromReturnType = true)
private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity);
@NodeIntrinsic(value = RawLoadNode.class)
private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter JavaKind wordKind);
@NodeIntrinsic(value = LoadHubNode.class)
public static native KlassPointer loadHubIntrinsic(Object object);
@ -803,6 +803,8 @@ public class HotSpotReplacementsUtil {
public static final LocationIdentity CLASS_MIRROR_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror");
public static final LocationIdentity CLASS_MIRROR_HANDLE_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror handle");
public static final LocationIdentity HEAP_TOP_LOCATION = NamedLocationIdentity.mutable("HeapTop");
@Fold

View File

@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot.replacements;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
import org.graalvm.compiler.graph.Node;
@ -70,7 +71,7 @@ public final class HubGetClassNode extends FloatingNode implements Lowerable, Ca
return null;
} else {
MetaAccessProvider metaAccess = tool.getMetaAccess();
if (metaAccess != null && hub.isConstant()) {
if (metaAccess != null && hub.isConstant() && !GraalOptions.ImmutableCode.getValue(graph().getOptions())) {
ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(hub.asConstant());
if (exactType != null) {
return ConstantNode.forConstant(tool.getConstantReflection().asJavaClass(exactType), metaAccess);

View File

@ -25,6 +25,9 @@ package org.graalvm.compiler.hotspot.replacements;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
@ -38,6 +41,7 @@ import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.extended.LoadHubNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
@ -63,6 +67,18 @@ public final class KlassLayoutHelperNode extends FloatingNode implements Canonic
this.klass = klass;
}
public static ValueNode create(GraalHotSpotVMConfig config, ValueNode klass, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess) {
Stamp stamp = StampFactory.forKind(JavaKind.Int);
return canonical(null, config, klass, stamp, constantReflection, metaAccess);
}
@SuppressWarnings("unused")
public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, @InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass) {
ValueNode valueNode = create(config, klass, b.getConstantReflection(), b.getMetaAccess());
b.push(JavaKind.Int, b.recursiveAppend(valueNode));
return true;
}
@Override
public boolean inferStamp() {
if (klass instanceof LoadHubNode) {
@ -92,10 +108,17 @@ public final class KlassLayoutHelperNode extends FloatingNode implements Canonic
if (tool.allUsagesAvailable() && hasNoUsages()) {
return null;
} else {
return canonical(this, config, klass, stamp(), tool.getConstantReflection(), tool.getMetaAccess());
}
}
private static ValueNode canonical(KlassLayoutHelperNode klassLayoutHelperNode, GraalHotSpotVMConfig config, ValueNode klass, Stamp stamp, ConstantReflectionProvider constantReflection,
MetaAccessProvider metaAccess) {
KlassLayoutHelperNode self = klassLayoutHelperNode;
if (klass.isConstant()) {
if (!klass.asConstant().isDefaultForKind()) {
Constant constant = stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), klass.asConstant(), config.klassLayoutHelperOffset);
return ConstantNode.forConstant(stamp(), constant, tool.getMetaAccess());
Constant constant = stamp.readConstant(constantReflection.getMemoryAccessProvider(), klass.asConstant(), config.klassLayoutHelperOffset);
return ConstantNode.forConstant(stamp, constant, metaAccess);
}
}
if (klass instanceof LoadHubNode) {
@ -106,13 +129,15 @@ public final class KlassLayoutHelperNode extends FloatingNode implements Canonic
HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) ostamp.type();
if (type != null && type.isArray() && !type.getComponentType().isPrimitive()) {
// The layout for all object arrays is the same.
Constant constant = stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), type.klass(), config.klassLayoutHelperOffset);
return ConstantNode.forConstant(stamp(), constant, tool.getMetaAccess());
Constant constant = stamp.readConstant(constantReflection.getMemoryAccessProvider(), type.klass(), config.klassLayoutHelperOffset);
return ConstantNode.forConstant(stamp, constant, metaAccess);
}
}
}
return this;
if (self == null) {
self = new KlassLayoutHelperNode(config, klass);
}
return self;
}
@Override

View File

@ -35,8 +35,10 @@ import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
import org.graalvm.compiler.nodes.java.LoadExceptionObjectNode;
@ -52,6 +54,7 @@ import org.graalvm.compiler.word.Word;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.ResolvedJavaType;
/**
* Snippet for loading the exception object at the start of an exception dispatcher.
@ -76,15 +79,19 @@ public class LoadExceptionObjectSnippets implements Snippets {
public static class Templates extends AbstractTemplates {
private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException", EXCEPTION_OOP_LOCATION, EXCEPTION_PC_LOCATION);
private final HotSpotWordTypes wordTypes;
public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) {
super(options, providers, providers.getSnippetReflection(), target);
this.wordTypes = providers.getWordTypes();
}
public void lower(LoadExceptionObjectNode loadExceptionObject, HotSpotRegistersProvider registers, LoweringTool tool) {
StructuredGraph graph = loadExceptionObject.graph();
if (LoadExceptionObjectInVM.getValue(graph.getOptions())) {
ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), true, false));
ResolvedJavaType wordType = providers.getMetaAccess().lookupJavaType(Word.class);
Stamp stamp = wordTypes.getWordStamp(wordType);
ReadRegisterNode thread = graph.add(new ReadRegisterNode(stamp, registers.getThreadRegister(), true, false));
graph.addBeforeFixed(loadExceptionObject, thread);
ForeignCallNode loadExceptionC = graph.add(new ForeignCallNode(providers.getForeignCalls(), LOAD_AND_CLEAR_EXCEPTION, thread));
loadExceptionC.setStateAfter(loadExceptionObject.stateAfter());

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