OpenJDK / amber / amber
changeset 46372:721b8f969cc8
Merge
author | iveresov |
---|---|
date | Thu, 06 Apr 2017 23:01:27 +0000 |
parents | 7a0ae73888ff 0337d0617e7b |
children | 6896a3ff27a8 |
files | |
diffstat | 226 files changed, 4090 insertions(+), 2177 deletions(-) [+] |
line wrap: on
line diff
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java Thu Apr 06 23:01:27 2017 +0000 @@ -54,12 +54,9 @@ import jdk.vm.ci.meta.TriState; public class AOTBackend { - private final Main main; private final OptionValues graalOptions; - private final HotSpotBackend backend; - private final HotSpotProviders providers; private final HotSpotCodeCacheProvider codeCache; private final PhaseSuite<HighTierContext> graphBuilderSuite; @@ -81,6 +78,10 @@ return graphBuilderSuite; } + public HotSpotBackend getBackend() { + return backend; + } + private Suites getSuites() { // create suites every time, as we modify options for the compiler return backend.getSuites().getDefaultSuites(graalOptions); @@ -189,7 +190,7 @@ public void printCompiledMethod(HotSpotResolvedJavaMethod resolvedMethod, CompilationResult compResult) { // This is really not installing the method. - InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(null, null, compResult), null, null); + InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult), null, null); String disassembly = codeCache.disassemble(installedCode); if (disassembly != null) { main.printlnDebug(disassembly);
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java Thu Apr 06 23:01:27 2017 +0000 @@ -145,7 +145,7 @@ aotBackend.printCompiledMethod((HotSpotResolvedJavaMethod) method, compResult); } - result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method)); + result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method, aotBackend.getBackend())); } private String getMethodDescription() {
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java Thu Apr 06 23:01:27 2017 +0000 @@ -24,6 +24,7 @@ package jdk.tools.jaotc; import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder; import jdk.vm.ci.hotspot.HotSpotCompiledCode; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; @@ -31,9 +32,11 @@ public class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo { private final HotSpotResolvedJavaMethod method; + private final Backend backend; - public AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method) { + public AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method, Backend backend) { this.method = method; + this.backend = backend; } public String getSymbolName() { @@ -46,7 +49,7 @@ } public HotSpotCompiledCode compiledCode(CompilationResult result) { - return HotSpotCompiledCodeBuilder.createCompiledCode(method, null, result); + return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), method, null, result); } }
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java Thu Apr 06 23:01:27 2017 +0000 @@ -49,7 +49,7 @@ } public HotSpotCompiledCode compiledCode(CompilationResult result) { - return HotSpotCompiledCodeBuilder.createCompiledCode(null, null, result); + return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), null, null, result); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -22,15 +22,16 @@ */ package org.graalvm.compiler.api.directives.test; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode; +import org.junit.Assert; +import org.junit.Test; public class ProbabilityDirectiveTest extends GraalCompilerTest { @@ -55,9 +56,21 @@ Assert.assertEquals("IfNode count", 1, ifNodes.count()); IfNode ifNode = ifNodes.first(); - AbstractBeginNode trueSuccessor = ifNode.trueSuccessor(); - Assert.assertEquals("branch probability of " + ifNode, 0.125, ifNode.probability(trueSuccessor), 0); + AbstractBeginNode oneSuccessor; + if (returnValue(ifNode.trueSuccessor()) == 1) { + oneSuccessor = ifNode.trueSuccessor(); + } else { + assert returnValue(ifNode.falseSuccessor()) == 1; + oneSuccessor = ifNode.falseSuccessor(); + } + Assert.assertEquals("branch probability of " + ifNode, 0.125, ifNode.probability(oneSuccessor), 0); return true; } + + private static int returnValue(AbstractBeginNode b) { + ControlFlowAnchorNode anchor = (ControlFlowAnchorNode) b.next(); + ReturnNode returnNode = (ReturnNode) anchor.next(); + return returnNode.result().asJavaConstant().asInt(); + } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java Thu Apr 06 23:01:27 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1757,6 +1757,10 @@ return constant.isNull() || isSimm(constant.asLong(), 5); } + public static boolean isSimm5(long imm) { + return isSimm(imm, 5); + } + public static boolean isSimm13(int imm) { return isSimm(imm, 13); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceStatisticsPrinter.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceStatisticsPrinter.java Thu Apr 06 23:01:27 2017 +0000 @@ -35,7 +35,7 @@ @SuppressWarnings("try") public static void printTraceStatistics(TraceBuilderResult result, String compilationUnitName) { try (Scope s = Debug.scope("DumpTraceStatistics")) { - if (Debug.isLogEnabled(Debug.VERBOSE_LOG_LEVEL)) { + if (Debug.isLogEnabled(Debug.VERBOSE_LEVEL)) { print(result, compilationUnitName); } } catch (Throwable e) { @@ -48,9 +48,9 @@ List<Trace> traces = result.getTraces(); int numTraces = traces.size(); - try (Indent indent0 = Debug.logAndIndent(Debug.VERBOSE_LOG_LEVEL, "<tracestatistics>")) { - Debug.log(Debug.VERBOSE_LOG_LEVEL, "<name>%s</name>", compilationUnitName != null ? compilationUnitName : "null"); - try (Indent indent1 = Debug.logAndIndent(Debug.VERBOSE_LOG_LEVEL, "<traces>")) { + try (Indent indent0 = Debug.logAndIndent(Debug.VERBOSE_LEVEL, "<tracestatistics>")) { + Debug.log(Debug.VERBOSE_LEVEL, "<name>%s</name>", compilationUnitName != null ? compilationUnitName : "null"); + try (Indent indent1 = Debug.logAndIndent(Debug.VERBOSE_LEVEL, "<traces>")) { printRawLine("tracenumber", "total", "min", "max", "numBlocks"); for (int i = 0; i < numTraces; i++) { AbstractBlockBase<?>[] t = traces.get(i).getBlocks(); @@ -70,14 +70,14 @@ printLine(i, total, min, max, t.length); } } - Debug.log(Debug.VERBOSE_LOG_LEVEL, "</traces>"); + Debug.log(Debug.VERBOSE_LEVEL, "</traces>"); } - Debug.log(Debug.VERBOSE_LOG_LEVEL, "</tracestatistics>"); + Debug.log(Debug.VERBOSE_LEVEL, "</tracestatistics>"); } private static void printRawLine(Object tracenr, Object totalTime, Object minProb, Object maxProb, Object numBlocks) { - Debug.log(Debug.VERBOSE_LOG_LEVEL, "%s", String.join(SEP, tracenr.toString(), totalTime.toString(), minProb.toString(), maxProb.toString(), numBlocks.toString())); + Debug.log(Debug.VERBOSE_LEVEL, "%s", String.join(SEP, tracenr.toString(), totalTime.toString(), minProb.toString(), maxProb.toString(), numBlocks.toString())); } private static void printLine(int tracenr, double totalTime, double minProb, double maxProb, int numBlocks) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java Thu Apr 06 23:01:27 2017 +0000 @@ -343,116 +343,7 @@ if (lt instanceof PrimitiveConstant) { PrimitiveConstant lp = (PrimitiveConstant) lt; PrimitiveConstant rp = (PrimitiveConstant) rt; - switch (lp.getJavaKind()) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: { - int x = lp.asInt(); - int y = rp.asInt(); - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - case AE: - return UnsignedMath.aboveOrEqual(x, y); - case BE: - return UnsignedMath.belowOrEqual(x, y); - case AT: - return UnsignedMath.aboveThan(x, y); - case BT: - return UnsignedMath.belowThan(x, y); - default: - throw new GraalError("expected condition: %s", this); - } - } - case Long: { - long x = lp.asLong(); - long y = rp.asLong(); - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - case AE: - return UnsignedMath.aboveOrEqual(x, y); - case BE: - return UnsignedMath.belowOrEqual(x, y); - case AT: - return UnsignedMath.aboveThan(x, y); - case BT: - return UnsignedMath.belowThan(x, y); - default: - throw new GraalError("expected condition: %s", this); - } - } - case Float: { - float x = lp.asFloat(); - float y = rp.asFloat(); - if (Float.isNaN(x) || Float.isNaN(y)) { - return unorderedIsTrue; - } - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - default: - throw new GraalError("expected condition: %s", this); - } - } - case Double: { - double x = lp.asDouble(); - double y = rp.asDouble(); - if (Double.isNaN(x) || Double.isNaN(y)) { - return unorderedIsTrue; - } - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - default: - throw new GraalError("expected condition: %s", this); - } - } - default: - throw new GraalError("expected value kind %s while folding condition: %s", lp.getJavaKind(), this); - } + return foldCondition(lp, rp, unorderedIsTrue); } else { Boolean equal = constantReflection.constantEquals(lt, rt); if (equal == null) { @@ -469,6 +360,128 @@ } } + /** + * Attempts to fold a comparison between two primitive constants and return the result. + * + * @param lp the constant on the left side of the comparison + * @param rp the constant on the right side of the comparison + * @param unorderedIsTrue true if an undecided float comparison should result in "true" + * @return true if the comparison is known to be true, false if the comparison is known to be + * false + */ + public boolean foldCondition(PrimitiveConstant lp, PrimitiveConstant rp, boolean unorderedIsTrue) { + switch (lp.getJavaKind()) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: { + int x = lp.asInt(); + int y = rp.asInt(); + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + case AE: + return UnsignedMath.aboveOrEqual(x, y); + case BE: + return UnsignedMath.belowOrEqual(x, y); + case AT: + return UnsignedMath.aboveThan(x, y); + case BT: + return UnsignedMath.belowThan(x, y); + default: + throw new GraalError("expected condition: %s", this); + } + } + case Long: { + long x = lp.asLong(); + long y = rp.asLong(); + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + case AE: + return UnsignedMath.aboveOrEqual(x, y); + case BE: + return UnsignedMath.belowOrEqual(x, y); + case AT: + return UnsignedMath.aboveThan(x, y); + case BT: + return UnsignedMath.belowThan(x, y); + default: + throw new GraalError("expected condition: %s", this); + } + } + case Float: { + float x = lp.asFloat(); + float y = rp.asFloat(); + if (Float.isNaN(x) || Float.isNaN(y)) { + return unorderedIsTrue; + } + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + default: + throw new GraalError("expected condition: %s", this); + } + } + case Double: { + double x = lp.asDouble(); + double y = rp.asDouble(); + if (Double.isNaN(x) || Double.isNaN(y)) { + return unorderedIsTrue; + } + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + default: + throw new GraalError("expected condition: %s", this); + } + } + default: + throw new GraalError("expected value kind %s while folding condition: %s", lp.getJavaKind(), this); + } + } + public Condition join(Condition other) { if (other == this) { return this;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java Thu Apr 06 23:01:27 2017 +0000 @@ -154,6 +154,7 @@ return Double.isNaN(lowerBound); } + @Override public boolean isUnrestricted() { return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN; }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java Thu Apr 06 23:01:27 2017 +0000 @@ -59,6 +59,11 @@ } @Override + public boolean isUnrestricted() { + return true; + } + + @Override public Stamp empty() { return this; }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java Thu Apr 06 23:01:27 2017 +0000 @@ -254,6 +254,7 @@ return upMask; } + @Override public boolean isUnrestricted() { return lowerBound == CodeUtil.minValue(getBits()) && upperBound == CodeUtil.maxValue(getBits()) && downMask == 0 && upMask == CodeUtil.mask(getBits()); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java Thu Apr 06 23:01:27 2017 +0000 @@ -126,6 +126,13 @@ } /** + * Tests whether this stamp represents all values of this kind. + */ + public boolean isUnrestricted() { + return this.equals(this.unrestricted()); + } + + /** * If this stamp represents a single value, the methods returns this single value. It returns * null otherwise. *
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java Thu Apr 06 23:01:27 2017 +0000 @@ -39,33 +39,6 @@ public class StampFactory { - /* - * The marker stamp for node intrinsics must be its own class, so that it is never equal() to a - * regular ObjectStamp. - */ - static final class NodeIntrinsicStamp extends ObjectStamp { - protected static final Stamp SINGLETON = new NodeIntrinsicStamp(); - - private NodeIntrinsicStamp() { - super(null, false, false, false); - } - - @Override - public int hashCode() { - return System.identityHashCode(this); - } - - @Override - public boolean equals(Object obj) { - return this == obj; - } - - @Override - public String toString() { - return "NodeIntrinsicStamp"; - } - } - // JaCoCo Exclude private static final Stamp[] stampCache = new Stamp[JavaKind.values().length]; @@ -143,14 +116,6 @@ return VoidStamp.getInstance(); } - /** - * A stamp used only in the graph of intrinsics, e.g., snippets. It is then replaced by an - * actual stamp when the intrinsic is used, i.e., when the snippet template is instantiated. - */ - public static Stamp forNodeIntrinsic() { - return NodeIntrinsicStamp.SINGLETON; - } - public static Stamp intValue() { return forKind(JavaKind.Int); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java Thu Apr 06 23:01:27 2017 +0000 @@ -46,6 +46,11 @@ } @Override + public boolean isUnrestricted() { + return true; + } + + @Override public JavaKind getStackKind() { return JavaKind.Void; }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java Thu Apr 06 23:01:27 2017 +0000 @@ -23,10 +23,10 @@ package org.graalvm.compiler.core.common.util; import java.util.ArrayList; -import java.util.HashMap; -import java.util.IdentityHashMap; import java.util.List; -import java.util.Map; + +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; /** * Creates an array of T objects order by the occurrence frequency of each object. The most @@ -49,24 +49,24 @@ } } - protected final Map<T, Entry<T>> map; + protected final EconomicMap<T, Entry<T>> map; protected boolean containsNull; /** * Creates an encoder that uses object identity. */ public static <T> FrequencyEncoder<T> createIdentityEncoder() { - return new FrequencyEncoder<>(new IdentityHashMap<>()); + return new FrequencyEncoder<>(EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE)); } /** * Creates an encoder that uses {@link Object#equals(Object) object equality}. */ public static <T> FrequencyEncoder<T> createEqualityEncoder() { - return new FrequencyEncoder<>(new HashMap<>()); + return new FrequencyEncoder<>(EconomicMap.create(Equivalence.DEFAULT)); } - protected FrequencyEncoder(Map<T, Entry<T>> map) { + protected FrequencyEncoder(EconomicMap<T, Entry<T>> map) { this.map = map; } @@ -91,7 +91,7 @@ * Returns the index of an object in the array. The object must have been * {@link #addObject(Object) added} before. */ - public int getIndex(Object object) { + public int getIndex(T object) { if (object == null) { assert containsNull; return 0; @@ -114,7 +114,10 @@ */ public T[] encodeAll(T[] allObjects) { assert allObjects.length == getLength(); - List<Entry<T>> sortedEntries = new ArrayList<>(map.values()); + List<Entry<T>> sortedEntries = new ArrayList<>(allObjects.length); + for (Entry<T> value : map.getValues()) { + sortedEntries.add(value); + } sortedEntries.sort((e1, e2) -> -Integer.compare(e1.frequency, e2.frequency)); int offset = 0;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java Thu Apr 06 23:01:27 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -202,7 +202,7 @@ private Variable emitUnary(Op3s op3, Value input) { Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - getLIRGen().append(SPARCOP3Op.newUnary(op3, input, result)); + getLIRGen().append(SPARCOP3Op.newUnary(op3, getLIRGen().loadSimm13(input), result)); return result; } @@ -227,9 +227,9 @@ private Variable emitBinary(ValueKind<?> resultKind, Op3s op3, Value a, Value b, LIRFrameState state) { Variable result = getLIRGen().newVariable(resultKind); if (op3.isCommutative() && isJavaConstant(a) && getLIRGen().getMoveFactory().canInlineConstant(asJavaConstant(a))) { - getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(b), a, result, state)); + getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(b), getLIRGen().loadSimm13(a), result, state)); } else { - getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(a), b, result, state)); + getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(a), getLIRGen().loadSimm13(b), result, state)); } return result; }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java Thu Apr 06 23:01:27 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -199,11 +199,11 @@ Condition actualCondition; if (isJavaConstant(x)) { left = load(y); - right = loadNonConst(x); + right = loadSimm13(x); actualCondition = cond.mirror(); } else { left = load(x); - right = loadNonConst(y); + right = loadSimm13(y); actualCondition = cond; } SPARCKind actualCmpKind = (SPARCKind) cmpKind; @@ -250,7 +250,7 @@ return load(value); } - private Value loadSimm13(Value value) { + public Value loadSimm13(Value value) { if (isJavaConstant(value)) { JavaConstant c = asJavaConstant(value); if (c.isNull() || SPARCAssembler.isSimm13(c)) { @@ -261,6 +261,13 @@ } @Override + public Value loadNonConst(Value value) { + // SPARC does not support a proper way of loadNonConst. Please use the appropriate + // loadSimm11 or loadSimm13 variants. + throw GraalError.shouldNotReachHere("This operation is not available for SPARC."); + } + + @Override public Variable emitConditionalMove(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { // Emit compare SPARCKind cmpSPARCKind = (SPARCKind) cmpKind;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -22,10 +22,6 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - import org.graalvm.compiler.loop.DefaultLoopPolicies; import org.graalvm.compiler.loop.phases.LoopPeelingPhase; import org.graalvm.compiler.nodes.ReturnNode; @@ -37,6 +33,9 @@ import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; /** * In the following tests, the usages of local variable "a" are replaced with the integer constant @@ -162,7 +161,7 @@ sum0 = a; } else { int sum = a; - for (int i = 0; i < n; i++) { + for (int i = 1; i < n; i++) { sum += i; } sum0 = sum;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest3.java Thu Apr 06 23:01:27 2017 +0000 @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; +import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Ignore; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +public class CompareCanonicalizerTest3 extends GraalCompilerTest { + + @SuppressWarnings("unused") private static int sink0; + @SuppressWarnings("unused") private static int sink1; + + @Test + public void test00() { + assertCanonicallyEqual("integerTestCanonicalization00", "referenceSnippet00"); + } + + public static void integerTestCanonicalization00(char a) { + if (a - 1 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @SuppressWarnings("unused") + public static void referenceSnippet00(char a) { + sink1 = 0; + } + + @Ignore("Needs better stamp support for unsigned ranges") + @Test + public void test01() { + assertCanonicallyEqual("integerTestCanonicalization01", "referenceSnippet01"); + } + + public static void integerTestCanonicalization01(char a) { + if (Integer.compareUnsigned(a - 1, a) < 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet01(char a) { + if (a != 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Ignore("Needs better stamp support for unsigned ranges") + @Test + public void test1() { + assertCanonicallyEqual("integerTestCanonicalization1", "referenceSnippet1"); + } + + public static void integerTestCanonicalization1(char a) { + if (Integer.compareUnsigned(a - 2, a) < 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet1(char a) { + if (Integer.compareUnsigned(a, 2) >= 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test2() { + assertCanonicallyEqual("integerTestCanonicalization2", "referenceSnippet2"); + } + + public static void integerTestCanonicalization2(int a) { + if (a - 1 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet2(int a) { + if (a != Integer.MIN_VALUE) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test3() { + assertCanonicallyEqual("integerTestCanonicalization3", "referenceSnippet3"); + } + + public static void integerTestCanonicalization3(int a) { + if (a - 2 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet3(int a) { + if (a >= Integer.MIN_VALUE + 2) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test4() { + assertCanonicallyEqual("integerTestCanonicalization4", "referenceSnippet4"); + } + + public static void integerTestCanonicalization4(int a) { + if (a + 1 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet4(int a) { + if (a == Integer.MAX_VALUE) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test5() { + assertCanonicallyEqual("integerTestCanonicalization5", "referenceSnippet5"); + } + + public static void integerTestCanonicalization5(int a) { + if (a + 2 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet5(int a) { + if (a > Integer.MAX_VALUE - 2) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test6() { + assertCanonicallyEqual("integerTestCanonicalization6", "referenceSnippet6"); + } + + public static void integerTestCanonicalization6(int a) { + if (a < a + 1) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet6(int a) { + if (a != Integer.MAX_VALUE) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test7() { + assertCanonicallyEqual("integerTestCanonicalization7", "referenceSnippet7"); + } + + public static void integerTestCanonicalization7(int a) { + if (a < a + 2) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet7(int a) { + if (a <= Integer.MAX_VALUE - 2) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + protected void assertCanonicallyEqual(String snippet, String reference) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + PhaseContext context = new PhaseContext(getProviders()); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + canonicalizer.apply(graph, context); + canonicalizer.apply(graph, context); + StructuredGraph referenceGraph = parseEager(reference, AllowAssumptions.YES); + canonicalizer.apply(referenceGraph, context); + canonicalizer.apply(referenceGraph, context); + assertEquals(referenceGraph, graph, true, true); + } + + @Override + protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { + return InlineInvokePlugin.InlineInfo.createStandardInlineInfo(method); + } +}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -32,8 +32,8 @@ public class ConditionalEliminationMulTest extends GraalCompilerTest { public static void snippet01(int a) { - if (a == 2) { - if (a * 3 != 6) { + if (a == 3) { + if (a * 11 != 33) { shouldBeOptimizedAway(); } } @@ -41,7 +41,7 @@ public static void snippet02(int a) { if (a == 0) { - if (a * 3 != 0) { + if (a * 11 != 0) { shouldBeOptimizedAway(); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest1.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest1.java Thu Apr 06 23:01:27 2017 +0000 @@ -22,25 +22,25 @@ */ package org.graalvm.compiler.core.test; +import org.graalvm.compiler.api.directives.GraalDirectives; import org.junit.Test; -import org.graalvm.compiler.api.directives.GraalDirectives; - /** * Collection of tests for * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those * that triggered bugs in this phase. */ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase { + protected static int sink3; private static final String REFERENCE_SNIPPET = "referenceSnippet"; @SuppressWarnings("all") - public static int referenceSnippet(int a) { + public static void referenceSnippet(int a) { if (a == 0) { - return 1; + sink1 = 1; } - return 0; + sink0 = 0; } @Test @@ -49,21 +49,21 @@ } @SuppressWarnings("all") - public static int test1Snippet(int a) { + public static void test1Snippet(int a) { if (a == 0) { if (a == 5) { - return 100; + sink2 = 100; } if (a > 100) { if (a == 0) { - return 200; + sink3 = 200; } } if (a != 2) { - return 1; + sink1 = 1; } } - return 0; + sink0 = 0; } @Test @@ -72,18 +72,18 @@ } @SuppressWarnings("all") - public static int test2Snippet(int a) { + public static void test2Snippet(int a) { if (a == 0) { if (a > 100) { if (a == 0) { - return 200; + sink3 = 200; } } if (a != 2) { - return 1; + sink1 = 1; } } - return 0; + sink0 = 0; } @Test @@ -92,7 +92,7 @@ } @SuppressWarnings("all") - public static int test3Snippet(int a) { + public static void test3Snippet(int a) { if (a == 0) { if (a < 1) { if (a < 2) { @@ -101,9 +101,9 @@ if (a > -2) { if (a > -3) { if (a == 1) { - return 42; + sink2 = 42; } else { - return 1; + sink1 = 1; } } } @@ -112,18 +112,18 @@ } } } - return 0; + sink0 = 0; } @SuppressWarnings("all") - public static int test4Snippet(int a, int b) { + public static void test4Snippet(int a, int b) { if (b < 1) { GraalDirectives.controlFlowAnchor(); if (b < 0) { - return 1; + sink1 = 1; } } - return 0; + sink0 = 0; } @Test @@ -132,21 +132,21 @@ } @SuppressWarnings("all") - public static int test5Snippet(int a, int b) { + public static void test5Snippet(int a, int b) { if ((b & 3) == 0) { GraalDirectives.controlFlowAnchor(); if ((b & 7) == 0) { GraalDirectives.controlFlowAnchor(); - return 1; + sink1 = 1; } } else { GraalDirectives.controlFlowAnchor(); if ((b & 1) == 0) { GraalDirectives.controlFlowAnchor(); - return 2; + sink2 = 2; } } - return 0; + sink0 = 0; } @Test
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java Thu Apr 06 23:01:27 2017 +0000 @@ -22,22 +22,16 @@ */ package org.graalvm.compiler.core.test; +import org.graalvm.compiler.api.directives.GraalDirectives; import org.junit.Ignore; import org.junit.Test; -import org.graalvm.compiler.api.directives.GraalDirectives; - /** * Collection of tests for * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those * that triggered bugs in this phase. */ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase { - public ConditionalEliminationTest11() { - // Don't disable simplification - super(false); - } - @SuppressWarnings("all") public static int referenceSnippet(int a) { if ((a & 15) != 15) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java Thu Apr 06 23:01:27 2017 +0000 @@ -34,13 +34,6 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class ConditionalEliminationTest13 extends ConditionalEliminationTestBase { - public ConditionalEliminationTest13() { - super(false); - } - - private static int sink0; - private static int sink1; - private static int sink2; @Override protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { @@ -317,7 +310,7 @@ super.prepareGraph(graph, canonicalizer, context, applyLowering); graph.clearAllStateAfter(); graph.setGuardsStage(StructuredGraph.GuardsStage.AFTER_FSA); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After preparation"); + Debug.dump(Debug.BASIC_LEVEL, graph, "After preparation"); canonicalizer.apply(graph, context); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java Thu Apr 06 23:01:27 2017 +0000 @@ -22,11 +22,10 @@ */ package org.graalvm.compiler.core.test; +import org.graalvm.compiler.api.directives.GraalDirectives; import org.junit.Ignore; import org.junit.Test; -import org.graalvm.compiler.api.directives.GraalDirectives; - /** * Collection of tests for * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those @@ -50,20 +49,20 @@ static final class DistinctB { } - public static int reference1Snippet(Object a) { + public static void reference1Snippet(Object a) { if (a instanceof B) { - return 1; + sink1 = 1; } - return 2; + sink2 = 2; } - public static int test1Snippet(Object a) { + public static void test1Snippet(Object a) { if (a instanceof B) { if (a instanceof A) { - return 1; + sink1 = 1; } } - return 2; + sink2 = 2; } @Test @@ -71,21 +70,21 @@ testConditionalElimination("test1Snippet", "reference1Snippet"); } - public static int reference2Snippet(A a) { + public static void reference2Snippet(A a) { if (a instanceof B) { - return 1; + sink1 = 1; } - return 2; + sink2 = 2; } - public static int test2Snippet(A a) { + public static void test2Snippet(A a) { if (a instanceof B) { B newVal = (B) a; if (newVal != null) { - return 1; + sink1 = 1; } } - return 2; + sink2 = 2; } @Test @@ -94,28 +93,28 @@ } @SuppressWarnings("unused") - public static int reference3Snippet(Object a, Object b) { + public static void reference3Snippet(Object a, Object b) { if (a instanceof DistinctA) { DistinctA proxyA = (DistinctA) a; if (b instanceof DistinctB) { - return 1; + sink1 = 1; } } - return 2; + sink2 = 2; } @SuppressWarnings("all") - public static int test3Snippet(Object a, Object b) { + public static void test3Snippet(Object a, Object b) { if (a instanceof DistinctA) { DistinctA proxyA = (DistinctA) a; if (b instanceof DistinctB) { if (proxyA == b) { - return 42; + sink0 = 42; } - return 1; + sink1 = 1; } } - return 2; + sink2 = 2; } @Test @@ -123,54 +122,54 @@ testConditionalElimination("test3Snippet", "reference3Snippet", true, false); } - public static int reference4Snippet(Object a) { + public static void reference4Snippet(Object a) { if (!(a instanceof B)) { GraalDirectives.deoptimizeAndInvalidate(); } - return 1; + sink1 = 1; } - public static int test4Snippet1(Object a) { + public static void test4Snippet1(Object a) { if (!(a instanceof B)) { GraalDirectives.deoptimizeAndInvalidate(); } if (!(a instanceof A)) { GraalDirectives.deoptimizeAndInvalidate(); } - return 1; + sink1 = 1; } - public static int test4Snippet2(Object a) { + public static void test4Snippet2(Object a) { if (!(a instanceof A)) { GraalDirectives.deoptimizeAndInvalidate(); } if (!(a instanceof B)) { GraalDirectives.deoptimizeAndInvalidate(); } - return 1; + sink1 = 1; } @SuppressWarnings({"cast", "unused"}) - public static int test4Snippet3(Object a) { + public static void test4Snippet3(Object a) { Object pi = (A) a; if (!(a instanceof B)) { GraalDirectives.deoptimizeAndInvalidate(); } - return 1; + sink1 = 1; } - public static int test4Snippet4(Object a) { + public static void test4Snippet4(Object a) { if (!(a instanceof A)) { GraalDirectives.deoptimizeAndInvalidate(); } if (!(((A) a) instanceof B)) { GraalDirectives.deoptimizeAndInvalidate(); } - return 1; + sink1 = 1; } @SuppressWarnings({"cast"}) - public static int test4Snippet5(Object a) { + public static void test4Snippet5(Object a) { Object pi = (A) a; if (pi == null) { GraalDirectives.deoptimizeAndInvalidate(); @@ -178,7 +177,7 @@ if (!(a instanceof B)) { GraalDirectives.deoptimizeAndInvalidate(); } - return 1; + sink1 = 1; } @Test
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Thu Apr 06 23:01:27 2017 +0000 @@ -42,15 +42,9 @@ * that triggered bugs in this phase. */ public class ConditionalEliminationTestBase extends GraalCompilerTest { - private final boolean disableSimplification; - - protected ConditionalEliminationTestBase() { - this(true); - } - - protected ConditionalEliminationTestBase(boolean disableSimplification) { - this.disableSimplification = disableSimplification; - } + protected static int sink0; + protected static int sink1; + protected static int sink2; protected void testConditionalElimination(String snippet, String referenceSnippet) { testConditionalElimination(snippet, referenceSnippet, false, false); @@ -59,15 +53,9 @@ @SuppressWarnings("try") protected void testConditionalElimination(String snippet, String referenceSnippet, boolean applyConditionalEliminationOnReference, boolean applyLowering) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); PhaseContext context = new PhaseContext(getProviders()); CanonicalizerPhase canonicalizer1 = new CanonicalizerPhase(); - if (disableSimplification) { - /** - * Some tests break if simplification is done so only do it when needed. - */ - canonicalizer1.disableSimplification(); - } CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); try (Debug.Scope scope = Debug.scope("ConditionalEliminationTest", graph)) { prepareGraph(graph, canonicalizer1, context, applyLowering);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DeMorganCanonicalizationTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.calc.AndNode; +import org.graalvm.compiler.nodes.calc.NotNode; +import org.graalvm.compiler.nodes.calc.OrNode; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.junit.Assert; +import org.junit.Test; + +public class DeMorganCanonicalizationTest extends GraalCompilerTest { + + public static int or(int a, int b) { + return ~a | ~b; + } + + public static int and(int a, int b) { + return ~a & ~b; + } + + @Test + public void testAnd() { + StructuredGraph g = parseEager("and", AllowAssumptions.NO, getInitialOptions()); + new CanonicalizerPhase().apply(g, getDefaultHighTierContext()); + Assert.assertEquals(1, g.getNodes().filter(OrNode.class).count()); + Assert.assertEquals(1, g.getNodes().filter(NotNode.class).count()); + + testAgainstExpected(g.method(), new Result(and(-1, 17), null), (Object) null, -1, 17); + testAgainstExpected(g.method(), new Result(and(-1, 1), null), (Object) null, -1, 1); + testAgainstExpected(g.method(), new Result(and(-1, -1), null), (Object) null, -1, -1); + testAgainstExpected(g.method(), new Result(and(Integer.MIN_VALUE, Integer.MIN_VALUE), null), (Object) null, Integer.MIN_VALUE, Integer.MIN_VALUE); + } + + @Test + public void testOr() { + StructuredGraph g = parseEager("or", AllowAssumptions.NO, getInitialOptions()); + new CanonicalizerPhase().apply(g, getDefaultHighTierContext()); + Assert.assertEquals(1, g.getNodes().filter(AndNode.class).count()); + Assert.assertEquals(1, g.getNodes().filter(NotNode.class).count()); + + testAgainstExpected(g.method(), new Result(or(-1, 17), null), (Object) null, -1, 17); + testAgainstExpected(g.method(), new Result(or(-1, 1), null), (Object) null, -1, 1); + testAgainstExpected(g.method(), new Result(or(-1, -1), null), (Object) null, -1, -1); + testAgainstExpected(g.method(), new Result(or(Integer.MIN_VALUE, Integer.MIN_VALUE), null), (Object) null, Integer.MIN_VALUE, Integer.MIN_VALUE); + } + +}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -86,9 +86,9 @@ HighTierContext context = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); new CanonicalizerPhase().apply(graph, context); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, referenceGraph, "ReferenceGraph"); + Debug.dump(Debug.BASIC_LEVEL, referenceGraph, "ReferenceGraph"); assertEquals(referenceGraph, graph); } catch (Throwable e) { throw Debug.handle(e);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueDefaultMethodTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueDefaultMethodTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -142,7 +142,7 @@ try (Scope s = Debug.scope("InstanceOfTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); compile(graph.method(), graph); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet); + Debug.dump(Debug.BASIC_LEVEL, graph, snippet); return graph; } catch (Throwable e) { throw Debug.handle(e);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -82,7 +82,7 @@ } } - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After lowering"); + Debug.dump(Debug.BASIC_LEVEL, graph, "After lowering"); Assert.assertNotNull(returnNode); Assert.assertNotNull(monitorexit);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -78,6 +78,7 @@ import org.graalvm.compiler.nodes.FullInfopointNode; import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.InvokeWithExceptionNode; +import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -91,6 +92,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.nodes.java.AccessFieldNode; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; @@ -121,6 +123,7 @@ import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.Assumptions.Assumption; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaKind; @@ -130,7 +133,6 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.SpeculationLog; -import jdk.vm.ci.meta.Assumptions.Assumption; import jdk.vm.ci.services.Services; /** @@ -410,13 +412,13 @@ String mismatchString = compareGraphStrings(expected, expectedString, graph, actualString); if (!excludeVirtual && getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "Node count not matching - expected"); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Node count not matching - actual"); + Debug.dump(Debug.BASIC_LEVEL, expected, "Node count not matching - expected"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Node count not matching - actual"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount() + "\n" + mismatchString); } if (!expectedString.equals(actualString)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "mismatching graphs - expected"); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "mismatching graphs - actual"); + Debug.dump(Debug.BASIC_LEVEL, expected, "mismatching graphs - expected"); + Debug.dump(Debug.BASIC_LEVEL, graph, "mismatching graphs - actual"); Assert.fail(mismatchString); } } @@ -482,22 +484,25 @@ StringBuilder result = new StringBuilder(); for (Block block : scheduleResult.getCFG().getBlocks()) { - result.append("Block " + block + " "); + result.append("Block ").append(block).append(' '); if (block == scheduleResult.getCFG().getStartBlock()) { result.append("* "); } result.append("-> "); for (Block succ : block.getSuccessors()) { - result.append(succ + " "); + result.append(succ).append(' '); } - result.append("\n"); + result.append('\n'); for (Node node : scheduleResult.getBlockToNodesMap().get(block)) { if (node instanceof ValueNode && node.isAlive()) { - if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode || node instanceof FullInfopointNode)) { + if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode || node instanceof FullInfopointNode || node instanceof ParameterNode)) { if (node instanceof ConstantNode) { String name = checkConstants ? node.toString(Verbosity.Name) : node.getClass().getSimpleName(); - String str = name + (excludeVirtual ? "\n" : " (" + filteredUsageCount(node) + ")\n"); - constantsLines.add(str); + if (excludeVirtual) { + constantsLines.add(name); + } else { + constantsLines.add(name + " (" + filteredUsageCount(node) + ")"); + } } else { int id; if (canonicalId.get(node) != null) { @@ -507,8 +512,17 @@ canonicalId.set(node, id); } String name = node.getClass().getSimpleName(); - String str = " " + id + "|" + name + (excludeVirtual ? "\n" : " (" + filteredUsageCount(node) + ")\n"); - result.append(str); + result.append(" ").append(id).append('|').append(name); + if (node instanceof AccessFieldNode) { + result.append('#'); + result.append(((AccessFieldNode) node).field()); + } + if (!excludeVirtual) { + result.append(" ("); + result.append(filteredUsageCount(node)); + result.append(')'); + } + result.append('\n'); } } } @@ -516,14 +530,14 @@ } StringBuilder constantsLinesResult = new StringBuilder(); - constantsLinesResult.append(constantsLines.size() + " constants:\n"); + constantsLinesResult.append(constantsLines.size()).append(" constants:\n"); Collections.sort(constantsLines); for (String s : constantsLines) { constantsLinesResult.append(s); - constantsLinesResult.append("\n"); + constantsLinesResult.append('\n'); } - return constantsLines.toString() + result.toString(); + return constantsLinesResult.toString() + result.toString(); } /** @@ -545,15 +559,15 @@ StringBuilder result = new StringBuilder(); Block[] blocks = scheduleResult.getCFG().getBlocks(); for (Block block : blocks) { - result.append("Block " + block + " "); + result.append("Block ").append(block).append(' '); if (block == scheduleResult.getCFG().getStartBlock()) { result.append("* "); } result.append("-> "); for (Block succ : block.getSuccessors()) { - result.append(succ + " "); + result.append(succ).append(' '); } - result.append("\n"); + result.append('\n'); for (Node node : scheduleResult.getBlockToNodesMap().get(block)) { result.append(String.format("%1S\n", node)); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -217,7 +217,7 @@ n.replaceFirstInput(param, constant); } } - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); for (FrameState fs : param.usages().filter(FrameState.class).snapshot()) { fs.replaceFirstInput(param, null);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -25,7 +25,8 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import org.junit.Test; - +import org.graalvm.compiler.loop.DefaultLoopPolicies; +import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.java.MonitorExitNode; @@ -91,6 +92,26 @@ assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count()); } + public void testUnrolledSyncSnippet(Object a) { + for (int i = 0; i < 3; i++) { + synchronized (a) { + + } + } + } + + @Test + public void testUnrolledSync() { + StructuredGraph graph = getGraph("testUnrolledSyncSnippet"); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + canonicalizer.apply(graph, new PhaseContext(getProviders())); + HighTierContext context = getDefaultHighTierContext(); + new LoopFullUnrollPhase(canonicalizer, new DefaultLoopPolicies()).apply(graph, context); + new LockEliminationPhase().apply(graph); + assertDeepEquals(1, graph.getNodes().filter(RawMonitorEnterNode.class).count()); + assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count()); + } + private StructuredGraph getGraph(String snippet) { ResolvedJavaMethod method = getResolvedJavaMethod(snippet); StructuredGraph graph = parseEager(method, AllowAssumptions.YES);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -717,7 +717,7 @@ if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { graph.clearAllStateAfter(); } - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "after removal of framestates"); + Debug.dump(Debug.BASIC_LEVEL, graph, "after removal of framestates"); new FloatingReadPhase().apply(graph); new RemoveValueProxyPhase().apply(graph);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -61,7 +61,7 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); assertDeepEquals(returnCount, graph.getNodes(ReturnNode.TYPE).count()); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -142,7 +142,7 @@ private void test(String snippet, int rootExits, int nestedExits, int innerExits) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); Assert.assertEquals(3, cfg.getLoops().size()); @@ -162,7 +162,7 @@ Assert.assertEquals(rootExits, rootLoop.getExits().size()); Assert.assertEquals(nestedExits, nestedLoop.getExits().size()); Assert.assertEquals(innerExits, innerMostLoop.getExits().size()); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); } private static boolean contains(Loop<Block> loop, Invoke node, ControlFlowGraph cfg) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -58,9 +58,11 @@ x = 2; sideEffect = null; } + int b = 4; sideEffect = null; + int c = b % 5; // can shift - return a * x * 4; + return a * x * c; } public static int test2Snippet(int a) { @@ -249,7 +251,7 @@ gc2.apply(g2, htc); Debug.log("Test Graph Cost --> 1.Graph cost:%f vs. 2.Graph cost:%f\n", gc1.finalCycles, gc2.finalCycles); Assert.assertTrue(gc2.finalCycles > gc1.finalCycles); - Assert.assertTrue(gc2.finalSize == gc1.finalSize + 1/* mul has 3 const input */); + Assert.assertTrue(gc2.finalSize == gc1.finalSize); } @Test
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PhiCreationTests.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PhiCreationTests.java Thu Apr 06 23:01:27 2017 +0000 @@ -70,7 +70,7 @@ @Test public void test3() { StructuredGraph graph = parseEager("test3Snippet", AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } @@ -86,7 +86,7 @@ @Test public void test4() { StructuredGraph graph = parseEager("test4Snippet", AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -59,7 +59,7 @@ private void test(String snippet, String reference) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); for (FrameState fs : graph.getNodes(FrameState.TYPE).snapshot()) { fs.replaceAtUsages(null); GraphUtil.killWithUnusedFloatingInputs(fs);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -94,7 +94,7 @@ new FloatingReadPhase().apply(graph); canonicalizer.apply(graph, context); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After lowering"); + Debug.dump(Debug.BASIC_LEVEL, graph, "After lowering"); for (FloatingReadNode node : graph.getNodes(ParameterNode.TYPE).first().usages().filter(FloatingReadNode.class)) { // Checking that the parameter a is not directly used for the access to field
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -131,7 +131,7 @@ private void test(final String snippet, final String referenceSnippet) { // No debug scope to reduce console noise for @Test(expected = ...) tests StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); PhaseContext context = new PhaseContext(getProviders()); new CanonicalizerPhase().apply(graph, context); StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java Thu Apr 06 23:01:27 2017 +0000 @@ -69,7 +69,7 @@ BeginNode beginNode = graph.add(new BeginNode()); returnNode.replaceAtPredecessor(beginNode); beginNode.setNext(returnNode); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST); schedulePhase.apply(graph); ScheduleResult schedule = graph.getLastSchedule();
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -41,7 +41,7 @@ public class SimpleCFGTest extends GraalCompilerTest { private static void dumpGraph(final StructuredGraph graph) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); } @Test
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -88,7 +88,7 @@ private void test(final String snippet) { // No debug scope to reduce console noise for @Test(expected = ...) tests StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); assertEquals(referenceGraph, graph);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -180,7 +180,7 @@ private void test(String snippet, String referenceSnippet) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); /* * When using FlowSensitiveReductionPhase instead of ConditionalEliminationPhase, * tail-duplication gets activated thus resulting in a graph with more nodes than the @@ -200,8 +200,8 @@ @Override protected void assertEquals(StructuredGraph expected, StructuredGraph graph) { if (getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "expected (node count)"); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "graph (node count)"); + Debug.dump(Debug.BASIC_LEVEL, expected, "expected (node count)"); + Debug.dump(Debug.BASIC_LEVEL, graph, "graph (node count)"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount()); } } @@ -244,7 +244,7 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph " + snippet); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph " + snippet); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext()); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -83,9 +83,28 @@ @Override protected void run(StructuredGraph graph) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "%s", graph.toString()); + Debug.dump(Debug.BASIC_LEVEL, graph, "%s", graph.toString()); + } + } + + private static class InvalidDumpLevelPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + Debug.dump(Debug.VERY_DETAILED_LEVEL + 1, graph, "%s", graph); + } + } + + private static class NonConstantDumpLevelPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + Debug.dump(getLevel(), graph, "%s", graph); } + int getLevel() { + return 10; + } } private static class InvalidVerifyUsagePhase extends Phase { @@ -126,7 +145,7 @@ @Override protected void run(StructuredGraph graph) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "error " + graph); + Debug.dump(Debug.BASIC_LEVEL, graph, "error " + graph); } } @@ -169,7 +188,7 @@ @Override protected void run(StructuredGraph graph) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "%s", graph); + Debug.dump(Debug.BASIC_LEVEL, graph, "%s", graph); } } @@ -234,6 +253,16 @@ } @Test(expected = VerificationError.class) + public void testDumpLevelInvalid() { + testDebugUsageClass(InvalidDumpLevelPhase.class); + } + + @Test(expected = VerificationError.class) + public void testDumpNonConstantLevelInvalid() { + testDebugUsageClass(NonConstantDumpLevelPhase.class); + } + + @Test(expected = VerificationError.class) public void testLogInvalidConcat() { testDebugUsageClass(InvalidConcatLogUsagePhase.class); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -135,6 +135,7 @@ } public static Object[] array = new Object[]{1, 2, 3, 4, 5, "asdf", "asdf"}; + public static char[] charArray = new char[]{1, 2, 3, 4, 5, 'a', 'f'}; public static Object testArrayCopySnippet(int a) { Object[] tmp = new Object[]{a != 1 ? array[a] : null}; @@ -144,6 +145,18 @@ } @Test + public void testPrimitiveArraycopy() { + testPartialEscapeAnalysis("testPrimitiveArraycopySnippet", 0, 0); + } + + public static Object testPrimitiveArraycopySnippet(int a) { + char[] tmp = new char[]{a != 1 ? charArray[a] : 0}; + char[] tmp2 = new char[5]; + System.arraycopy(tmp, 0, tmp2, 4, 1); + return tmp2[4]; + } + + @Test @Ignore public void testCache() { testPartialEscapeAnalysis("testCacheSnippet", 0.75, 1);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -244,10 +244,10 @@ ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)) : getDefaultGraphBuilderSuite(); HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, context); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); return graph;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -121,7 +121,7 @@ long start = System.currentTimeMillis(); phase.apply(g, context); long end = System.currentTimeMillis(); - Debug.dump(Debug.DETAILED_LOG_LEVEL, g, "After %s", phase.contractorName()); + Debug.dump(Debug.DETAILED_LEVEL, g, "After %s", phase.contractorName()); return end - start; } @@ -138,7 +138,7 @@ next = callerGraph.getNodes(MethodCallTargetNode.TYPE).first().invoke(); EconomicSet<Node> canonicalizeNodes = InliningUtil.inlineForCanonicalization(next, calleeGraph, false, calleeMethod); canonicalizer.applyIncremental(callerGraph, context, canonicalizeNodes); - Debug.dump(Debug.DETAILED_LOG_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i); + Debug.dump(Debug.DETAILED_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i); } return callerGraph; }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/GraalTutorial.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/GraalTutorial.java Thu Apr 06 23:01:27 2017 +0000 @@ -25,6 +25,8 @@ import org.junit.Assert; import org.junit.Test; +import java.util.regex.Pattern; + import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeDisassembler; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; @@ -56,7 +58,11 @@ byte[] bytecodes = bytecode.getCode(); Assert.assertNotNull(bytecodes); - System.out.println(new BytecodeDisassembler().disassemble(bytecode)); + Pattern disassemblyLineRE = Pattern.compile(" *\\d+: [a-z][\\w_]+"); + String disassembly = new BytecodeDisassembler().disassemble(bytecode); + for (String line : disassembly.split("\\n")) { + Assert.assertTrue(line, disassemblyLineRE.matcher(line).find()); + } } /*
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java Thu Apr 06 23:01:27 2017 +0000 @@ -39,6 +39,7 @@ import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.debug.DebugTimer; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.MethodFilter; import org.graalvm.compiler.debug.internal.method.MethodMetricsRootScopeInfo; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.alloc.OutOfRegistersException; @@ -175,11 +176,43 @@ } catch (Throwable e) { throw Debug.handle(e); } + checkForRequestedCrash(r.graph); return r.compilationResult; } } /** + * Checks whether the {@link GraalCompilerOptions#CrashAt} option indicates that the compilation + * of {@code graph} should result in an exception. + * + * @param graph a graph currently being compiled + * @throws RuntimeException if the value of {@link GraalCompilerOptions#CrashAt} matches + * {@code graph.method()} or {@code graph.name} + */ + private static void checkForRequestedCrash(StructuredGraph graph) { + String methodPattern = GraalCompilerOptions.CrashAt.getValue(graph.getOptions()); + if (methodPattern != null) { + String crashLabel = null; + ResolvedJavaMethod method = graph.method(); + if (method == null) { + if (graph.name.contains(methodPattern)) { + crashLabel = graph.name; + } + } else { + MethodFilter[] filters = MethodFilter.parse(methodPattern); + for (MethodFilter filter : filters) { + if (filter.matches(method)) { + crashLabel = method.format("%H.%n(%p)"); + } + } + } + if (crashLabel != null) { + throw new RuntimeException("Forced crash after compiling " + crashLabel); + } + } + } + + /** * Builds the graph, optimizes it. */ @SuppressWarnings("try") @@ -190,21 +223,25 @@ if (graph.start().next() == null) { graphBuilderSuite.apply(graph, highTierContext); new DeadCodeEliminationPhase(DeadCodeEliminationPhase.Optionality.Optional).apply(graph); + Debug.dump(Debug.BASIC_LEVEL, graph, "After parsing"); } else { - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "initial state"); + Debug.dump(Debug.INFO_LEVEL, graph, "initial state"); } suites.getHighTier().apply(graph, highTierContext); graph.maybeCompress(); + Debug.dump(Debug.BASIC_LEVEL, graph, "After high tier"); MidTierContext midTierContext = new MidTierContext(providers, target, optimisticOpts, profilingInfo); suites.getMidTier().apply(graph, midTierContext); graph.maybeCompress(); + Debug.dump(Debug.BASIC_LEVEL, graph, "After mid tier"); LowTierContext lowTierContext = new LowTierContext(providers, target); suites.getLowTier().apply(graph, lowTierContext); + Debug.dump(Debug.BASIC_LEVEL, graph, "After low tier"); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph.getLastSchedule(), "Final HIR schedule"); + Debug.dump(Debug.BASIC_LEVEL, graph.getLastSchedule(), "Final HIR schedule"); } catch (Throwable e) { throw Debug.handle(e); } finally { @@ -269,7 +306,7 @@ linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock); lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions()); - Debug.dump(Debug.INFO_LOG_LEVEL, lir, "After linear scan order"); + Debug.dump(Debug.INFO_LEVEL, lir, "After linear scan order"); } catch (Throwable e) { throw Debug.handle(e); } @@ -283,9 +320,9 @@ new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context); try (Scope s = Debug.scope("LIRStages", nodeLirGen, lir)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, lir, "After LIR generation"); + Debug.dump(Debug.BASIC_LEVEL, lir, "After LIR generation"); LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo)); - Debug.dump(Debug.BASIC_LOG_LEVEL, lir, "Before code generation"); + Debug.dump(Debug.BASIC_LEVEL, lir, "Before code generation"); return result; } catch (Throwable e) { throw Debug.handle(e); @@ -365,7 +402,7 @@ Debug.counter("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size()); } - Debug.dump(Debug.BASIC_LOG_LEVEL, compilationResult, "After code generation"); + Debug.dump(Debug.BASIC_LEVEL, compilationResult, "After code generation"); } } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java Thu Apr 06 23:01:27 2017 +0000 @@ -46,6 +46,8 @@ public static final OptionKey<Boolean> ExitVMOnException = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) public static final OptionKey<Boolean> PrintStackTraceOnException = new OptionKey<>(false); + @Option(help = "Pattern (see MethodFilter for format) for method that will trigger an exception when compiled. " + + "This option exists to test handling compilation crashes gracefully.", type = OptionType.Debug) + public static final OptionKey<String> CrashAt = new OptionKey<>(null); // @formatter:on - }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java Thu Apr 06 23:01:27 2017 +0000 @@ -91,12 +91,12 @@ listener = new HashSetNodeEventListener(); try (NodeEventScope s = graph.trackNodeEvents(listener)) { try (Scope s2 = Debug.scope("WithGraphChangeMonitoring")) { - if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "*** Before phase %s", getName()); + if (Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) { + Debug.dump(Debug.DETAILED_LEVEL, graph, "*** Before phase %s", getName()); } super.run(graph, context); - if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "*** After phase %s %s", getName(), filteredNodes); + if (Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) { + Debug.dump(Debug.DETAILED_LEVEL, graph, "*** After phase %s %s", getName(), filteredNodes); } Debug.log("*** %s %s %s\n", message, graph, filteredNodes); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java Thu Apr 06 23:01:27 2017 +0000 @@ -122,11 +122,41 @@ return config.isDumpEnabledForMethod(); } - public static final int BASIC_LOG_LEVEL = 1; - public static final int INFO_LOG_LEVEL = 2; - public static final int VERBOSE_LOG_LEVEL = 3; - public static final int DETAILED_LOG_LEVEL = 4; - public static final int VERY_DETAILED_LOG_LEVEL = 5; + /** + * Basic debug level. + * + * For HIR dumping, only ~5 graphs per method: after parsing, after inlining, after high tier, + * after mid tier, after low tier. + */ + public static final int BASIC_LEVEL = 1; + + /** + * Informational debug level. + * + * HIR dumping: One graph after each applied top-level phase. + */ + public static final int INFO_LEVEL = 2; + + /** + * Verbose debug level. + * + * HIR dumping: One graph after each phase (including sub phases). + */ + public static final int VERBOSE_LEVEL = 3; + + /** + * Detailed debug level. + * + * HIR dumping: Graphs within phases where interesting for a phase, max ~5 per phase. + */ + public static final int DETAILED_LEVEL = 4; + + /** + * Very detailed debug level. + * + * HIR dumping: Graphs per node granularity graph change (before/after change). + */ + public static final int VERY_DETAILED_LEVEL = 5; public static boolean isDumpEnabled(int dumpLevel) { return ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel); @@ -183,7 +213,7 @@ } public static boolean isLogEnabled() { - return isLogEnabled(BASIC_LOG_LEVEL); + return isLogEnabled(BASIC_LEVEL); } public static boolean isLogEnabled(int logLevel) { @@ -420,7 +450,7 @@ } public static void log(String msg) { - log(BASIC_LOG_LEVEL, msg); + log(BASIC_LEVEL, msg); } /** @@ -435,7 +465,7 @@ } public static void log(String format, Object arg) { - log(BASIC_LOG_LEVEL, format, arg); + log(BASIC_LEVEL, format, arg); } /** @@ -451,7 +481,7 @@ } public static void log(String format, int arg) { - log(BASIC_LOG_LEVEL, format, arg); + log(BASIC_LEVEL, format, arg); } /** @@ -467,7 +497,7 @@ } public static void log(String format, Object arg1, Object arg2) { - log(BASIC_LOG_LEVEL, format, arg1, arg2); + log(BASIC_LEVEL, format, arg1, arg2); } /** @@ -480,7 +510,7 @@ } public static void log(String format, int arg1, Object arg2) { - log(BASIC_LOG_LEVEL, format, arg1, arg2); + log(BASIC_LEVEL, format, arg1, arg2); } /** @@ -493,7 +523,7 @@ } public static void log(String format, Object arg1, int arg2) { - log(BASIC_LOG_LEVEL, format, arg1, arg2); + log(BASIC_LEVEL, format, arg1, arg2); } /** @@ -506,7 +536,7 @@ } public static void log(String format, int arg1, int arg2) { - log(BASIC_LOG_LEVEL, format, arg1, arg2); + log(BASIC_LEVEL, format, arg1, arg2); } /** @@ -519,7 +549,7 @@ } public static void log(String format, Object arg1, Object arg2, Object arg3) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); + log(BASIC_LEVEL, format, arg1, arg2, arg3); } /** @@ -532,7 +562,7 @@ } public static void log(String format, int arg1, int arg2, int arg3) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); + log(BASIC_LEVEL, format, arg1, arg2, arg3); } /** @@ -545,7 +575,7 @@ } public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4); + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4); } /** @@ -558,7 +588,7 @@ } public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5); + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5); } /** @@ -571,7 +601,7 @@ } public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); } /** @@ -584,11 +614,11 @@ } public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } /** @@ -607,7 +637,7 @@ } public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); } public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { @@ -617,7 +647,7 @@ } public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); } public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { @@ -627,7 +657,7 @@ } public static void logv(String format, Object... args) { - logv(BASIC_LOG_LEVEL, format, args); + logv(BASIC_LEVEL, format, args); } /** @@ -655,7 +685,7 @@ @Deprecated public static void log(String format, Object[] args) { assert false : "shouldn't use this"; - log(BASIC_LOG_LEVEL, format, args); + log(BASIC_LEVEL, format, args); } /** @@ -670,6 +700,14 @@ logv(logLevel, format, args); } + /** + * Forces an unconditional dump. This method exists mainly for debugging. It can also be used to + * force a graph dump from IDEs that support invoking a Java method while at a breakpoint. + */ + public static void forceDump(Object object, String format, Object... args) { + DebugScope.forceDump(object, format, args); + } + public static void dump(int dumpLevel, Object object, String msg) { if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) { DebugScope.getInstance().dump(dumpLevel, object, msg); @@ -771,7 +809,7 @@ } public static Indent logAndIndent(String msg) { - return logAndIndent(BASIC_LOG_LEVEL, msg); + return logAndIndent(BASIC_LEVEL, msg); } /** @@ -789,7 +827,7 @@ } public static Indent logAndIndent(String format, Object arg) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg); + return logAndIndent(BASIC_LEVEL, format, arg); } /** @@ -808,7 +846,7 @@ } public static Indent logAndIndent(String format, int arg) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg); + return logAndIndent(BASIC_LEVEL, format, arg); } /** @@ -827,7 +865,7 @@ } public static Indent logAndIndent(String format, int arg1, Object arg2) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); } /** @@ -841,7 +879,7 @@ } public static Indent logAndIndent(String format, Object arg1, int arg2) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); } /** @@ -855,7 +893,7 @@ } public static Indent logAndIndent(String format, int arg1, int arg2) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); } /** @@ -869,7 +907,7 @@ } public static Indent logAndIndent(String format, Object arg1, Object arg2) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); } /** @@ -883,7 +921,7 @@ } public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); } /** @@ -897,7 +935,7 @@ } public static Indent logAndIndent(String format, int arg1, int arg2, int arg3) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); } /** @@ -911,7 +949,7 @@ } public static Indent logAndIndent(String format, Object arg1, int arg2, int arg3) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); } /** @@ -925,7 +963,7 @@ } public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4); } /** @@ -939,7 +977,7 @@ } public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5); } /** @@ -953,7 +991,7 @@ } public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); } /** @@ -1001,7 +1039,7 @@ @Deprecated public static void logAndIndent(String format, Object[] args) { assert false : "shouldn't use this"; - logAndIndent(BASIC_LOG_LEVEL, format, args); + logAndIndent(BASIC_LEVEL, format, args); } /**
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugFilter.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugFilter.java Thu Apr 06 23:01:27 2017 +0000 @@ -41,28 +41,28 @@ * A filter is a list of comma-separated terms of the form {@code <pattern>[:<level>]}. {@code * <pattern>} is interpreted as a glob pattern if it contains a "*" or "?" character. Otherwise, it * is interpreted as a substring. If {@code <pattern>} is empty, it matches every scope. If {@code : - * <level>} is omitted, it defaults to {@link Debug#BASIC_LOG_LEVEL}. The term {@code ~<pattern>} is - * a shorthand for {@code <pattern>:0} to disable a debug facility for a pattern. + * <level>} is omitted, it defaults to {@link Debug#BASIC_LEVEL}. The term {@code ~<pattern>} is a + * shorthand for {@code <pattern>:0} to disable a debug facility for a pattern. * <p> * The resulting log level of a scope is determined by the <em>last</em> matching term. If no term * matches, the log level is 0 (disabled). A filter with no terms matches every scope with a log - * level of {@link Debug#BASIC_LOG_LEVEL}. + * level of {@link Debug#BASIC_LEVEL}. * * <h2>Examples of filters</h2> * * <ul> * <li>(empty string)<br> - * Matches any scope with log level {@link Debug#BASIC_LOG_LEVEL}. + * Matches any scope with log level {@link Debug#BASIC_LEVEL}. * * <li>{@code :1}<br> * Matches any scope with log level 1. * * <li>{@code *}<br> - * Matches any scope with log level {@link Debug#BASIC_LOG_LEVEL}. + * Matches any scope with log level {@link Debug#BASIC_LEVEL}. * * <li>{@code CodeGen,CodeInstall}<br> * Matches scopes containing "CodeGen" or "CodeInstall", both with log level - * {@link Debug#BASIC_LOG_LEVEL}. + * {@link Debug#BASIC_LEVEL}. * * <li>{@code CodeGen:2,CodeInstall:1}<br> * Matches scopes containing "CodeGen" with log level 2, or "CodeInstall" with log level 1. @@ -74,10 +74,10 @@ * Matches all scopes with log level 1, except those containing "Dead". * * <li>{@code Code*}<br> - * Matches scopes starting with "Code" with log level {@link Debug#BASIC_LOG_LEVEL}. + * Matches scopes starting with "Code" with log level {@link Debug#BASIC_LEVEL}. * * <li>{@code Code,~Dead}<br> - * Matches scopes containing "Code" but not "Dead", with log level {@link Debug#BASIC_LOG_LEVEL}. + * Matches scopes containing "Code" but not "Dead", with log level {@link Debug#BASIC_LEVEL}. * </ul> */ final class DebugFilter { @@ -108,7 +108,7 @@ level = 0; } else { pattern = t; - level = Debug.BASIC_LOG_LEVEL; + level = Debug.BASIC_LEVEL; } } else { pattern = t.substring(0, idx); @@ -119,13 +119,13 @@ } catch (NumberFormatException e) { switch (levelString) { case "basic": - level = Debug.BASIC_LOG_LEVEL; + level = Debug.BASIC_LEVEL; break; case "info": - level = Debug.INFO_LOG_LEVEL; + level = Debug.INFO_LEVEL; break; case "verbose": - level = Debug.VERBOSE_LOG_LEVEL; + level = Debug.VERBOSE_LEVEL; break; default: throw new IllegalArgumentException("Unknown dump level: \"" + levelString + "\" expected basic, info, verbose or an integer"); @@ -133,7 +133,7 @@ } } else { - level = Debug.BASIC_LOG_LEVEL; + level = Debug.BASIC_LEVEL; } } @@ -147,7 +147,7 @@ */ public int matchLevel(String input) { if (terms == null) { - return Debug.BASIC_LOG_LEVEL; + return Debug.BASIC_LEVEL; } else { int level = 0; for (Term t : terms) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugRetryableTask.java Thu Apr 06 23:01:27 2017 +0000 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import org.graalvm.compiler.debug.Debug.Scope; + +/** + * A mechanism for re-executing a task upon failure. + */ +public abstract class DebugRetryableTask<T> extends DelegatingDebugConfig { + + /** + * Calls {@link #run} on this task and if it results in an exception, calls + * {@link #onRetry(Throwable)} and if that returns {@code true}, calls {@link #run}. + */ + @SuppressWarnings("try") + public final T execute() { + try { + return run(null); + } catch (Throwable t) { + if (onRetry(t)) { + try (Scope d = Debug.sandbox("Retrying: " + this, this)) { + return run(t); + } catch (Throwable t2) { + throw Debug.handle(t2); + } + } else { + throw t; + } + } + } + + /** + * Runs this task. + * + * @param failure the cause of the first execution to fail or {@code null} if this is the first + * execution of {@link #run(Throwable)} + */ + protected abstract T run(Throwable failure); + + /** + * Notifies this object that the initial execution failed with exception {@code t} and is about + * to be re-executed. The re-execution will use this object as the active {@link DebugConfig}. + * As such, this method can be overridden to enable more detailed debug facilities. + * + * @param t an exception that terminated the first execution of this task + * @return whether this task should be re-executed. If false, {@code t} will be re-thrown. + */ + protected boolean onRetry(Throwable t) { + return true; + } +}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java Thu Apr 06 23:01:27 2017 +0000 @@ -79,7 +79,9 @@ @Option(help = "Write debug values into a file instead of the terminal. " + "If DebugValueSummary is Thread, the thread name will be prepended.", type = OptionType.Debug) public static final OptionKey<String> DebugValueFile = new OptionKey<>(null); - @Option(help = "Send Graal compiler IR to dump handlers on error", type = OptionType.Debug) + @Option(help = "Enable debug output for stub code generation and snippet preparation.", type = OptionType.Debug) + public static final OptionKey<Boolean> DebugStubsAndSnippets = new OptionKey<>(false); + @Option(help = "Send Graal compiler IR to dump handlers on error.", type = OptionType.Debug) public static final OptionKey<Boolean> DumpOnError = new OptionKey<>(false); @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug) public static final OptionKey<Boolean> InterceptBailout = new OptionKey<>(false); @@ -406,7 +408,7 @@ if (e instanceof BailoutException && !Options.InterceptBailout.getValue(options)) { return null; } - Debug.setConfig(Debug.fixedConfig(options, Debug.BASIC_LOG_LEVEL, Debug.BASIC_LOG_LEVEL, false, false, false, false, false, dumpHandlers, verifyHandlers, output)); + Debug.setConfig(Debug.fixedConfig(options, Debug.BASIC_LEVEL, Debug.BASIC_LEVEL, false, false, false, false, false, dumpHandlers, verifyHandlers, output)); Debug.log("Exception occurred in scope: %s", Debug.currentScope()); Map<Object, Object> firstSeen = new IdentityHashMap<>(); for (Object o : Debug.context()) { @@ -414,7 +416,7 @@ if (!firstSeen.containsKey(o)) { firstSeen.put(o, o); if (Options.DumpOnError.getValue(options) || Options.Dump.getValue(options) != null) { - Debug.dump(Debug.BASIC_LOG_LEVEL, o, "Exception: %s", e); + Debug.dump(Debug.BASIC_LEVEL, o, "Exception: %s", e); } else { Debug.log("Context obj %s", o); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java Thu Apr 06 23:01:27 2017 +0000 @@ -352,7 +352,7 @@ dumpHandler.dump(object, message); } } else { - TTY.println("Forced dump ignored because debugging is disabled - use -Dgraal.Dump=xxx"); + TTY.println("Forced dump ignored because debugging is disabled - use -Dgraal.ForceDebugEnable=true"); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Thu Apr 06 23:01:27 2017 +0000 @@ -405,6 +405,13 @@ return add(node); } + public <T extends Node> T maybeAddOrUnique(T node) { + if (node.isAlive()) { + return node; + } + return addOrUnique(node); + } + public <T extends Node> T addOrUniqueWithInputs(T node) { if (node.isAlive()) { assert node.graph() == this;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java Thu Apr 06 23:01:27 2017 +0000 @@ -40,6 +40,8 @@ import java.util.function.Predicate; import org.graalvm.compiler.core.common.Fields; +import org.graalvm.compiler.core.common.type.AbstractPointerStamp; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.Fingerprint; import org.graalvm.compiler.graph.Graph.NodeEvent; @@ -131,7 +133,9 @@ * Denotes an injected parameter in a {@linkplain NodeIntrinsic node intrinsic} constructor. If * the constructor is called as part of node intrinsification, the node intrinsifier will inject * an argument for the annotated parameter. Injected parameters must precede all non-injected - * parameters in a constructor. + * parameters in a constructor. If the type of the annotated parameter is {@link Stamp}, the + * {@linkplain Stamp#javaType type} of the injected stamp is the return type of the annotated + * method (which cannot be {@code void}). */ @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) @java.lang.annotation.Target(ElementType.PARAMETER) @@ -140,40 +144,45 @@ /** * Annotates a method that can be replaced by a compiler intrinsic. A (resolved) call to the - * annotated method can be replaced with an instance of the node class denoted by - * {@link #value()}. For this reason, the signature of the annotated method must match the - * signature (excluding a prefix of {@linkplain InjectedNodeParameter injected} parameters) of a - * constructor in the node class. + * annotated method will be processed by a generated {@code InvocationPlugin} that calls either + * a factory method or a constructor corresponding with the annotated method. * <p> - * If the node class has a static method {@code intrinsify} with a matching signature plus a - * {@code GraphBuilderContext} as first argument, this method is called instead of creating the - * node. + * A factory method corresponding to an annotated method is a static method named + * {@code intrinsify} defined in the class denoted by {@link #value()}. In order, its signature + * is as follows: + * <ol> + * <li>A {@code GraphBuilderContext} parameter.</li> + * <li>A {@code ResolvedJavaMethod} parameter.</li> + * <li>A sequence of zero or more {@linkplain InjectedNodeParameter injected} parameters.</li> + * <li>Remaining parameters that match the declared parameters of the annotated method.</li> + * </ol> + * A constructor corresponding to an annotated method is defined in the class denoted by + * {@link #value()}. In order, its signature is as follows: + * <ol> + * <li>A sequence of zero or more {@linkplain InjectedNodeParameter injected} parameters.</li> + * <li>Remaining parameters that match the declared parameters of the annotated method.</li> + * </ol> + * There must be exactly one such factory method or constructor corresponding to a + * {@link NodeIntrinsic} annotated method. */ @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) @java.lang.annotation.Target(ElementType.METHOD) public static @interface NodeIntrinsic { /** - * Gets the {@link Node} subclass instantiated when intrinsifying a call to the annotated - * method. If not specified, then the class in which the annotated method is declared is - * used (and is assumed to be a {@link Node} subclass). + * The class declaring the factory method or {@link Node} subclass declaring the constructor + * used to intrinsify a call to the annotated method. The default value is the class in + * which the annotated method is declared. */ Class<?> value() default NodeIntrinsic.class; /** - * Determines if the stamp of the instantiated intrinsic node has its stamp set from the - * return type of the annotated method. - * <p> - * When it is set to true, the stamp that is passed in to the constructor of ValueNode is - * ignored and can therefore safely be {@code null}. + * If {@code true}, the factory method or constructor selected by the annotation must have + * an {@linkplain InjectedNodeParameter injected} {@link Stamp} parameter. Calling + * {@link AbstractPointerStamp#nonNull()} on the injected stamp is guaranteed to return + * {@code true}. */ - boolean setStampFromReturnType() default false; - - /** - * Determines if the stamp of the instantiated intrinsic node is guaranteed to be non-null. - * Generally used in conjunction with {@link #setStampFromReturnType()}. - */ - boolean returnStampIsNonNull() default false; + boolean injectedStampIsNonNull() default false; } /** @@ -304,7 +313,7 @@ * @return an {@link NodeIterable iterable} for all non-null successor edges. */ public NodeIterable<Node> successors() { - assert !this.isDeleted(); + assert !this.isDeleted() : this; return nodeClass.getSuccessorIterable(this); } @@ -328,7 +337,7 @@ if (usage1 == null) { return 1; } - return 2 + extraUsagesCount; + return INLINE_USAGE_COUNT + extraUsagesCount; } /** @@ -391,30 +400,45 @@ } private void movUsageFromEndTo(int destIndex) { - int lastIndex = this.getUsageCount() - 1; - if (destIndex == 0) { - if (lastIndex == 0) { - usage0 = null; - return; - } else if (lastIndex == 1) { - usage0 = usage1; - usage1 = null; - return; - } else { - usage0 = extraUsages[lastIndex - INLINE_USAGE_COUNT]; - } + if (destIndex >= INLINE_USAGE_COUNT) { + movUsageFromEndToExtraUsages(destIndex - INLINE_USAGE_COUNT); } else if (destIndex == 1) { - if (lastIndex == 1) { - usage1 = null; - return; - } - usage1 = extraUsages[lastIndex - INLINE_USAGE_COUNT]; + movUsageFromEndToIndexOne(); } else { - Node n = extraUsages[lastIndex - INLINE_USAGE_COUNT]; - extraUsages[destIndex - INLINE_USAGE_COUNT] = n; + assert destIndex == 0; + movUsageFromEndToIndexZero(); } - extraUsages[lastIndex - INLINE_USAGE_COUNT] = null; + } + + private void movUsageFromEndToExtraUsages(int destExtraIndex) { this.extraUsagesCount--; + Node n = extraUsages[extraUsagesCount]; + extraUsages[destExtraIndex] = n; + extraUsages[extraUsagesCount] = null; + } + + private void movUsageFromEndToIndexZero() { + if (extraUsagesCount > 0) { + this.extraUsagesCount--; + usage0 = extraUsages[extraUsagesCount]; + extraUsages[extraUsagesCount] = null; + } else if (usage1 != null) { + usage0 = usage1; + usage1 = null; + } else { + usage0 = null; + } + } + + private void movUsageFromEndToIndexOne() { + if (extraUsagesCount > 0) { + this.extraUsagesCount--; + usage1 = extraUsages[extraUsagesCount]; + extraUsages[extraUsagesCount] = null; + } else { + assert usage1 != null; + usage1 = null; + } } /** @@ -425,20 +449,21 @@ */ public boolean removeUsage(Node node) { assert node != null; - // It is critical that this method maintains the invariant that - // the usage list has no null element preceding a non-null element + // For large graphs, usage removal is performance critical. + // Furthermore, it is critical that this method maintains the invariant that the usage list + // has no null element preceding a non-null element. incUsageModCount(); if (usage0 == node) { - this.movUsageFromEndTo(0); + movUsageFromEndToIndexZero(); return true; } if (usage1 == node) { - this.movUsageFromEndTo(1); + movUsageFromEndToIndexOne(); return true; } for (int i = this.extraUsagesCount - 1; i >= 0; i--) { if (extraUsages[i] == node) { - this.movUsageFromEndTo(i + INLINE_USAGE_COUNT); + movUsageFromEndToExtraUsages(i); return true; } } @@ -537,8 +562,9 @@ assert assertTrue(id == INITIAL_ID, "unexpected id: %d", id); this.graph = newGraph; newGraph.register(this); - this.getNodeClass().registerAtInputsAsUsage(this); - this.getNodeClass().registerAtSuccessorsAsPredecessor(this); + NodeClass<? extends Node> nc = nodeClass; + nc.registerAtInputsAsUsage(this); + nc.registerAtSuccessorsAsPredecessor(this); } /** @@ -588,7 +614,7 @@ } public final void replaceAtUsages(Node other) { - replaceAtUsages(other, null, null); + replaceAtAllUsages(other, (Node) null); } public final void replaceAtUsages(Node other, Predicate<Node> filter) { @@ -606,22 +632,60 @@ } protected void replaceAtUsages(Node other, Predicate<Node> filter, Node toBeDeleted) { + if (filter == null) { + replaceAtAllUsages(other, toBeDeleted); + } else { + replaceAtMatchingUsages(other, filter, toBeDeleted); + } + } + + protected void replaceAtAllUsages(Node other, Node toBeDeleted) { + assert checkReplaceWith(other); + if (usage0 == null) { + return; + } + replaceAtUsage(other, toBeDeleted, usage0); + usage0 = null; + + if (usage1 == null) { + return; + } + replaceAtUsage(other, toBeDeleted, usage1); + usage1 = null; + + if (extraUsagesCount <= 0) { + return; + } + for (int i = 0; i < extraUsagesCount; i++) { + Node usage = extraUsages[i]; + replaceAtUsage(other, toBeDeleted, usage); + } + this.extraUsages = NO_NODES; + this.extraUsagesCount = 0; + } + + private void replaceAtUsage(Node other, Node toBeDeleted, Node usage) { + boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); + assert assertTrue(result, "not found in inputs, usage: %s", usage); + /* + * Don't notify for nodes which are about to be deleted. + */ + if (toBeDeleted == null || usage != toBeDeleted) { + maybeNotifyInputChanged(usage); + } + if (other != null) { + other.addUsage(usage); + } + } + + private void replaceAtMatchingUsages(Node other, Predicate<Node> filter, Node toBeDeleted) { + assert filter != null; assert checkReplaceWith(other); int i = 0; while (i < this.getUsageCount()) { Node usage = this.getUsageAt(i); if (filter == null || filter.test(usage)) { - boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); - assert assertTrue(result, "not found in inputs, usage: %s", usage); - /* - * Don't notify for nodes which are about to be deleted. - */ - if (toBeDeleted == null || usage != toBeDeleted) { - maybeNotifyInputChanged(usage); - } - if (other != null) { - other.addUsage(usage); - } + replaceAtUsage(other, toBeDeleted, usage); this.movUsageFromEndTo(i); } else { ++i; @@ -641,21 +705,7 @@ public void replaceAtMatchingUsages(Node other, NodePredicate usagePredicate) { assert checkReplaceWith(other); - int index = 0; - while (index < this.getUsageCount()) { - Node usage = getUsageAt(index); - if (usagePredicate.apply(usage)) { - boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); - assert assertTrue(result, "not found in inputs, usage: %s", usage); - if (other != null) { - maybeNotifyInputChanged(usage); - other.addUsage(usage); - } - this.movUsageFromEndTo(index); - } else { - index++; - } - } + replaceAtMatchingUsages(other, usagePredicate, null); } public void replaceAtUsages(InputType type, Node other) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java Thu Apr 06 23:01:27 2017 +0000 @@ -154,7 +154,7 @@ if (bits.length < other.bits.length) { bits = Arrays.copyOf(bits, other.bits.length); } - for (int i = 0; i < bits.length; i++) { + for (int i = 0; i < Math.min(bits.length, other.bits.length); i++) { bits[i] |= other.bits[i]; } } @@ -181,44 +181,47 @@ } } - private static class MarkedNodeIterator implements Iterator<Node> { + protected int nextMarkedNodeId(int fromNodeId) { + assert fromNodeId >= 0; + int wordIndex = fromNodeId >> SHIFT; + int wordsInUse = bits.length; + if (wordIndex < wordsInUse) { + long word = bits[wordIndex] & (0xFFFFFFFFFFFFFFFFL << fromNodeId); + while (true) { + if (word != 0) { + return wordIndex * Long.SIZE + Long.numberOfTrailingZeros(word); + } + if (++wordIndex == wordsInUse) { + break; + } + word = bits[wordIndex]; + } + } + return -2; + } - private final NodeBitMap visited; - private Iterator<Node> nodes; - private Node nextNode; + private class MarkedNodeIterator implements Iterator<Node> { + private int nextNodeId; - MarkedNodeIterator(NodeBitMap visited, Iterator<Node> nodes) { - this.visited = visited; - this.nodes = nodes; + MarkedNodeIterator() { + nextNodeId = -1; forward(); } private void forward() { - do { - if (!nodes.hasNext()) { - nextNode = null; - return; - } - nextNode = nodes.next(); - if (visited.isNew(nextNode)) { - nextNode = null; - return; - } - } while (!visited.isMarked(nextNode)); + nextNodeId = NodeBitMap.this.nextMarkedNodeId(nextNodeId + 1); } @Override public boolean hasNext() { - return nextNode != null; + return nextNodeId >= 0; } @Override public Node next() { - try { - return nextNode; - } finally { - forward(); - } + Node result = graph.getNode(nextNodeId); + forward(); + return result; } @Override @@ -230,7 +233,7 @@ @Override public Iterator<Node> iterator() { - return new MarkedNodeIterator(NodeBitMap.this, graph().getNodes().iterator()); + return new MarkedNodeIterator(); } public NodeBitMap copy() {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java Thu Apr 06 23:01:27 2017 +0000 @@ -599,23 +599,24 @@ } private static boolean deepEquals0(Object e1, Object e2) { - assert e1 != null; - if (e2 == null) { + if (e1 == e2) { + return true; + } else if (e1 == null || e2 == null) { return false; - } else if (e1 instanceof Object[] && e2 instanceof Object[]) { - return Arrays.deepEquals((Object[]) e1, (Object[]) e2); } else if (!e1.getClass().isArray() || e1.getClass() != e2.getClass()) { return e1.equals(e2); - } else if (e1 instanceof byte[]) { - return Arrays.equals((byte[]) e1, (byte[]) e2); - } else if (e1 instanceof short[]) { - return Arrays.equals((short[]) e1, (short[]) e2); + } else if (e1 instanceof Object[] && e2 instanceof Object[]) { + return deepEquals((Object[]) e1, (Object[]) e2); } else if (e1 instanceof int[]) { return Arrays.equals((int[]) e1, (int[]) e2); } else if (e1 instanceof long[]) { return Arrays.equals((long[]) e1, (long[]) e2); + } else if (e1 instanceof byte[]) { + return Arrays.equals((byte[]) e1, (byte[]) e2); } else if (e1 instanceof char[]) { return Arrays.equals((char[]) e1, (char[]) e2); + } else if (e1 instanceof short[]) { + return Arrays.equals((short[]) e1, (short[]) e2); } else if (e1 instanceof float[]) { return Arrays.equals((float[]) e1, (float[]) e2); } else if (e1 instanceof double[]) { @@ -627,6 +628,20 @@ } } + private static boolean deepEquals(Object[] a1, Object[] a2) { + int length = a1.length; + if (a2.length != length) { + return false; + } + + for (int i = 0; i < length; i++) { + if (!deepEquals0(a1[i], a2[i])) { + return false; + } + } + return true; + } + public boolean dataEquals(Node a, Node b) { assert a.getClass() == b.getClass(); for (int i = 0; i < data.getCount(); ++i) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java Thu Apr 06 23:01:27 2017 +0000 @@ -23,14 +23,17 @@ package org.graalvm.compiler.graph; public final class NodeStack { - - private static final int INITIAL_SIZE = 8; + private static final int DEFAULT_INITIAL_SIZE = 8; protected Node[] values; public int tos; public NodeStack() { - values = new Node[INITIAL_SIZE]; + this(DEFAULT_INITIAL_SIZE); + } + + public NodeStack(int initialSize) { + values = new Node[initialSize]; } public int size() {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java Thu Apr 06 23:01:27 2017 +0000 @@ -27,7 +27,7 @@ import java.util.NoSuchElementException; import java.util.Queue; -import org.graalvm.compiler.core.common.PermanentBailoutException; +import org.graalvm.compiler.debug.Debug; public abstract class NodeWorkList implements Iterable<Node> { @@ -72,26 +72,19 @@ } public static final class IterativeNodeWorkList extends NodeWorkList { - private static final int HARD_ITERATION_LIMIT = 1_000_000; private static final int EXPLICIT_BITMAP_THRESHOLD = 10; protected NodeBitMap inQueue; private int iterationLimit; - private boolean hardLimit; private Node firstNoChange; private Node lastPull; private Node lastChain; public IterativeNodeWorkList(Graph graph, boolean fill, int iterationLimitPerNode) { super(graph, fill); - if (iterationLimitPerNode > 0) { - long limit = (long) iterationLimitPerNode * graph.getNodeCount(); - iterationLimit = (int) Long.min(Integer.MAX_VALUE, limit); - hardLimit = false; - } else { - iterationLimit = HARD_ITERATION_LIMIT; - hardLimit = true; - } + assert iterationLimitPerNode > 0; + long limit = (long) iterationLimitPerNode * graph.getNodeCount(); + iterationLimit = (int) Long.min(Integer.MAX_VALUE, limit); } @Override @@ -101,11 +94,8 @@ public boolean hasNext() { dropDeleted(); if (iterationLimit <= 0) { - if (hardLimit) { - throw new PermanentBailoutException("Iteration limit reached"); - } else { - return false; - } + Debug.log(Debug.INFO_LEVEL, "Exceeded iteration limit in IterativeNodeWorkList"); + return false; } return !worklist.isEmpty(); } @@ -152,7 +142,7 @@ } } } - assert checkInfiniteWork(node) : "Readded " + node; + assert checkInfiniteWork(node) : "Re-added " + node; if (inQueue != null) { inQueue.markAndGrow(node); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicate.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicate.java Thu Apr 06 23:01:27 2017 +0000 @@ -22,13 +22,20 @@ */ package org.graalvm.compiler.graph.iterators; +import java.util.function.Predicate; + import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodePredicates.AndPredicate; -public interface NodePredicate { +public interface NodePredicate extends Predicate<Node> { boolean apply(Node n); + @Override + default boolean test(Node n) { + return apply(n); + } + default NodePredicate and(NodePredicate np) { return new AndPredicate(this, np); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java Thu Apr 06 23:01:27 2017 +0000 @@ -105,6 +105,7 @@ return !a.apply(n); } + @Override public NodePredicate negate() { return a; } @@ -148,6 +149,7 @@ return this; } + @Override public NodePredicate negate() { return new NegativeTypePredicate(this); } @@ -183,6 +185,7 @@ return this; } + @Override public NodePredicate negate() { return new PositiveTypePredicate(this); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu Apr 06 23:01:27 2017 +0000 @@ -557,7 +557,7 @@ LIR lir = getResult().getLIR(); ArrayList<LIRInstruction> instructions = lir.getLIRforBlock(lir.getControlFlowGraph().getStartBlock()); instructions.add(1, op); - Debug.dump(Debug.INFO_LOG_LEVEL, lir, "created rescue dummy op"); + Debug.dump(Debug.INFO_LEVEL, lir, "created rescue dummy op"); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ClassSubstitutionsTests.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ClassSubstitutionsTests.java Thu Apr 06 23:01:27 2017 +0000 @@ -48,7 +48,7 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); compile(graph.method(), graph); assertNotInGraph(graph, Invoke.class); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet); + Debug.dump(Debug.BASIC_LEVEL, graph, snippet); return graph; } catch (Throwable e) { throw Debug.handle(e);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -47,7 +47,7 @@ System.setProperty(CompileTheWorld.LIMITMODS_PROPERTY_NAME, "java.base"); OptionValues initialOptions = getInitialOptions(); EconomicMap<OptionKey<?>, Object> compilationOptions = CompileTheWorld.parseOptions("Inline=false"); - new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, true, initialOptions, compilationOptions).compile(); + new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, false, initialOptions, compilationOptions).compile(); assert ExitVMOnException.getValue(initialOptions) == originalSetting; } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java Thu Apr 06 23:01:27 2017 +0000 @@ -57,7 +57,7 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); compile(graph.method(), graph); assertNotInGraph(graph, Invoke.class); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet); + Debug.dump(Debug.BASIC_LEVEL, graph, snippet); return graph; } catch (Throwable e) { throw Debug.handle(e); @@ -117,59 +117,32 @@ } } - /** - * Disables these tests until we know how to dynamically export the {@code jdk.internal.reflect} - * package from the {@code java.base} module to the unnamed module associated with - * {@link AsmLoader}. Without such an export, the test fails as follows: - * - * <pre> - * Caused by: java.lang.IllegalAccessError: class org.graalvm.compiler.hotspot.test.ConstantPoolTest - * (in unnamed module @0x57599b23) cannot access class jdk.internal.reflect.ConstantPool (in - * module java.base) because module java.base does not export jdk.internal.reflect to unnamed - * module @0x57599b23 - * </pre> - */ - private static void assumeJDK8() { - // Assume.assumeTrue(Java8OrEarlier); - } - @Test public void testGetSize() { - assumeJDK8(); Object cp = getConstantPoolForObject(); test("getSize", cp); } @Test public void testGetIntAt() { - assumeJDK8(); test("getIntAt"); } @Test public void testGetLongAt() { - assumeJDK8(); test("getLongAt"); } @Test public void testGetFloatAt() { - assumeJDK8(); test("getFloatAt"); } @Test public void testGetDoubleAt() { - assumeJDK8(); test("getDoubleAt"); } - // @Test - public void testGetUTF8At() { - assumeJDK8(); - test("getUTF8At"); - } - private static final String PACKAGE_NAME = ConstantPoolSubstitutionsTests.class.getPackage().getName(); private static final String PACKAGE_NAME_INTERNAL = PACKAGE_NAME.replace('.', '/');
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -53,6 +53,7 @@ import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import jdk.vm.ci.code.BytecodeFrame; +import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.VirtualObject; import jdk.vm.ci.code.site.InfopointReason; import jdk.vm.ci.common.JVMCIError; @@ -140,8 +141,9 @@ graph.addAfterFixed(graph.start(), test); CompilationResult compResult = compile(method, graph); - HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(method, null, compResult); - getCodeCache().addCode(method, compiledCode, null, null); + CodeCacheProvider codeCache = getCodeCache(); + HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, method, null, compResult); + codeCache.addCode(method, compiledCode, null, null); } @Test(expected = JVMCIError.class)
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -58,7 +58,11 @@ @Override @SuppressWarnings("try") protected Suites createSuites(OptionValues options) { - return super.createSuites(new OptionValues(options, GraalOptions.ImmutableCode, true)); + return super.createSuites(getOptions()); + } + + private static OptionValues getOptions() { + return new OptionValues(getInitialOptions(), GraalOptions.ImmutableCode, true); } @Override @@ -77,7 +81,7 @@ @Test public void testClassConstant() { - test("classConstant"); + test(getOptions(), "classConstant"); } public static Class<?> primitiveClassConstant() { @@ -86,7 +90,7 @@ @Test public void testPrimitiveClassConstant() { - test("primitiveClassConstant"); + test(getOptions(), "primitiveClassConstant"); } public static Wrapper compressedClassConstant(Wrapper w) { @@ -97,7 +101,7 @@ @Test public void testCompressedClassConstant() { ArgSupplier arg = () -> new Wrapper(); - test("compressedClassConstant", arg); + test(getOptions(), "compressedClassConstant", arg); } public static Wrapper compressedPrimitiveClassConstant(Wrapper w) { @@ -108,6 +112,6 @@ @Test public void testCompressedPrimitiveClassConstant() { ArgSupplier arg = () -> new Wrapper(); - test("compressedPrimitiveClassConstant", arg); + test(getOptions(), "compressedPrimitiveClassConstant", arg); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/RetryableCompilationTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.test; + +import static org.graalvm.compiler.test.SubprocessUtil.formatExecutedCommand; +import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine; +import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.hotspot.CompilationTask; +import org.junit.Assert; +import org.junit.Test; + +/** + * Tests {@link CompilationTask} support for dumping graphs and other info useful for debugging a + * compiler crash. + */ +public class RetryableCompilationTest extends GraalCompilerTest { + @Test + public void test() throws IOException { + List<String> args = withoutDebuggerArguments(getVMCommandLine()); + + args.add("-XX:+BootstrapJVMCI"); + args.add("-XX:+UseJVMCICompiler"); + args.add("-Dgraal.CrashAt=Object.*,String.*"); + args.add("-version"); + + ProcessBuilder processBuilder = new ProcessBuilder(args); + processBuilder.redirectErrorStream(true); + Process process = processBuilder.start(); + BufferedReader stdout = new BufferedReader(new InputStreamReader(process.getInputStream())); + + String forcedCrashString = "Forced crash after compiling"; + String diagnosticOutputFilePrefix = "Graal diagnostic output saved in "; + + boolean seenForcedCrashString = false; + String diagnosticOutputZip = null; + + List<String> outputLines = new ArrayList<>(); + + String line; + while ((line = stdout.readLine()) != null) { + outputLines.add(line); + if (line.contains(forcedCrashString)) { + seenForcedCrashString = true; + } else if (diagnosticOutputZip == null) { + int index = line.indexOf(diagnosticOutputFilePrefix); + if (index != -1) { + diagnosticOutputZip = line.substring(diagnosticOutputFilePrefix.length()).trim(); + } + } + } + String dashes = "-------------------------------------------------------"; + if (!seenForcedCrashString) { + Assert.fail(String.format("Did not find '%s' in output of command:%n%s", forcedCrashString, formatExecutedCommand(args, outputLines, dashes, dashes))); + } + if (diagnosticOutputZip == null) { + Assert.fail(String.format("Did not find '%s' in output of command:%n%s", diagnosticOutputFilePrefix, formatExecutedCommand(args, outputLines, dashes, dashes))); + } + + File zip = new File(diagnosticOutputZip).getAbsoluteFile(); + Assert.assertTrue(zip.toString(), zip.exists()); + try { + int bgv = 0; + int cfg = 0; + ZipFile dd = new ZipFile(diagnosticOutputZip); + List<String> entries = new ArrayList<>(); + for (Enumeration<? extends ZipEntry> e = dd.entries(); e.hasMoreElements();) { + ZipEntry ze = e.nextElement(); + String name = ze.getName(); + entries.add(name); + if (name.endsWith(".bgv")) { + bgv++; + } else if (name.endsWith(".cfg")) { + cfg++; + } + } + if (bgv == 0) { + Assert.fail(String.format("Expected at least one .bgv file in %s: %s", diagnosticOutputZip, entries)); + } + if (cfg == 0) { + Assert.fail(String.format("Expected at least one .cfg file in %s: %s", diagnosticOutputZip, entries)); + } + } finally { + zip.delete(); + } + } +}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -266,7 +266,7 @@ new GuardLoweringPhase().apply(graph, midContext); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); new WriteBarrierAdditionPhase(config).apply(graph); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After Write Barrier Addition"); + Debug.dump(Debug.BASIC_LEVEL, graph, "After Write Barrier Addition"); int barriers = 0; if (config.useG1GC) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Thu Apr 06 23:01:27 2017 +0000 @@ -30,7 +30,20 @@ import static org.graalvm.compiler.core.GraalCompilerOptions.PrintFilter; import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException; import static org.graalvm.compiler.core.phases.HighTier.Options.Inline; +import static org.graalvm.compiler.debug.Debug.INFO_LEVEL; +import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.DUMP_METHOD; +import static org.graalvm.compiler.debug.DelegatingDebugConfig.Level.DUMP; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DumpPath; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.ForceDebugEnable; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintCFGFileName; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintGraphFile; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintGraphFileName; import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import org.graalvm.compiler.code.CompilationResult; @@ -38,7 +51,9 @@ import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.DebugDumpHandler; import org.graalvm.compiler.debug.DebugDumpScope; +import org.graalvm.compiler.debug.DebugRetryableTask; import org.graalvm.compiler.debug.DebugTimer; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Management; @@ -46,6 +61,7 @@ import org.graalvm.compiler.debug.TimeSource; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.printer.GraalDebugConfigCustomizer; import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.BailoutException; @@ -96,6 +112,136 @@ private final boolean useProfilingInfo; private final OptionValues options; + final class RetryableCompilation extends DebugRetryableTask<HotSpotCompilationRequestResult> { + private final EventProvider.CompilationEvent compilationEvent; + CompilationResult result; + + RetryableCompilation(EventProvider.CompilationEvent compilationEvent) { + this.compilationEvent = compilationEvent; + } + + @SuppressWarnings("try") + @Override + protected HotSpotCompilationRequestResult run(Throwable retryCause) { + HotSpotResolvedJavaMethod method = getMethod(); + int entryBCI = getEntryBCI(); + final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; + CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR); + final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed(); + final boolean printAfterCompilation = PrintAfterCompilation.getValue(options) && !TTY.isSuppressed(); + if (printCompilation) { + TTY.println(getMethodDescription() + "..."); + } + + TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(options), method); + final long start; + final long allocatedBytesBefore; + if (printAfterCompilation || printCompilation) { + final long threadId = Thread.currentThread().getId(); + start = TimeSource.getTimeNS(); + allocatedBytesBefore = printAfterCompilation || printCompilation ? Lazy.threadMXBean.getThreadAllocatedBytes(threadId) : 0L; + } else { + start = 0L; + allocatedBytesBefore = 0L; + } + + try (Scope s = Debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { + // Begin the compilation event. + compilationEvent.begin(); + result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options); + } catch (Throwable e) { + throw Debug.handle(e); + } finally { + // End the compilation event. + compilationEvent.end(); + + filter.remove(); + + if (printAfterCompilation || printCompilation) { + final long threadId = Thread.currentThread().getId(); + final long stop = TimeSource.getTimeNS(); + final long duration = (stop - start) / 1000000; + final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1; + final int bytecodeSize = result != null ? result.getBytecodeSize() : 0; + final long allocatedBytesAfter = Lazy.threadMXBean.getThreadAllocatedBytes(threadId); + final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024; + + if (printAfterCompilation) { + TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); + } else if (printCompilation) { + TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dB %5dkB", getId(), "", "", "", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); + } + } + } + + if (result != null) { + try (DebugCloseable b = CodeInstallationTime.start()) { + installMethod(result); + } + } + stats.finish(method, installedCode); + if (result != null) { + return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize()); + } + return null; + } + + @Override + protected boolean onRetry(Throwable t) { + if (t instanceof BailoutException) { + return false; + } + + if (!Debug.isEnabled()) { + TTY.printf("Error while processing %s.%nRe-run with -D%s%s=true to capture graph dumps upon a compilation failure.%n", CompilationTask.this, + HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX, ForceDebugEnable.getName()); + return false; + } + + if (Dump.hasBeenSet(options)) { + // If dumping is explicitly enabled, Graal is being debugged + // so don't interfere with what the user is expecting to see. + return false; + } + + String outputDirectory = compiler.getGraalRuntime().getOutputDirectory(); + if (outputDirectory == null) { + return false; + } + String methodFQN = getMethod().format("%H.%n"); + File dumpPath = new File(outputDirectory, methodFQN); + dumpPath.mkdirs(); + if (!dumpPath.exists()) { + TTY.println("Warning: could not create dump directory " + dumpPath); + return false; + } + + TTY.println("Retrying " + CompilationTask.this); + retryDumpHandlers = new ArrayList<>(); + retryOptions = new OptionValues(options, + PrintGraphFile, true, + PrintCFGFileName, methodFQN, + PrintGraphFileName, methodFQN, + DumpPath, dumpPath.getPath()); + override(DUMP, INFO_LEVEL).enable(DUMP_METHOD); + new GraalDebugConfigCustomizer().customize(this); + return true; + } + + private Collection<DebugDumpHandler> retryDumpHandlers; + private OptionValues retryOptions; + + @Override + public Collection<DebugDumpHandler> dumpHandlers() { + return retryDumpHandlers; + } + + @Override + public OptionValues getOptions() { + return retryOptions; + } + } + static class Lazy { /** * A {@link com.sun.management.ThreadMXBean} to be able to query some information about the @@ -196,9 +342,8 @@ public HotSpotCompilationRequestResult runCompilation() { HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime(); GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); - final long threadId = Thread.currentThread().getId(); int entryBCI = getEntryBCI(); - final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; + boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; HotSpotResolvedJavaMethod method = getMethod(); // register the compilation id in the method metrics @@ -220,64 +365,9 @@ return null; } - CompilationResult result = null; + RetryableCompilation compilation = new RetryableCompilation(compilationEvent); try (DebugCloseable a = CompilationTime.start()) { - CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR); - final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed(); - final boolean printAfterCompilation = PrintAfterCompilation.getValue(options) && !TTY.isSuppressed(); - if (printCompilation) { - TTY.println(getMethodDescription() + "..."); - } - - TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(options), method); - final long start; - final long allocatedBytesBefore; - if (printAfterCompilation || printCompilation) { - start = TimeSource.getTimeNS(); - allocatedBytesBefore = printAfterCompilation || printCompilation ? Lazy.threadMXBean.getThreadAllocatedBytes(threadId) : 0L; - } else { - start = 0L; - allocatedBytesBefore = 0L; - } - - try (Scope s = Debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { - // Begin the compilation event. - compilationEvent.begin(); - result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options); - } catch (Throwable e) { - throw Debug.handle(e); - } finally { - // End the compilation event. - compilationEvent.end(); - - filter.remove(); - - if (printAfterCompilation || printCompilation) { - final long stop = TimeSource.getTimeNS(); - final long duration = (stop - start) / 1000000; - final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1; - final int bytecodeSize = result != null ? result.getBytecodeSize() : 0; - final long allocatedBytesAfter = Lazy.threadMXBean.getThreadAllocatedBytes(threadId); - final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024; - - if (printAfterCompilation) { - TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); - } else if (printCompilation) { - TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dB %5dkB", getId(), "", "", "", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); - } - } - } - - if (result != null) { - try (DebugCloseable b = CodeInstallationTime.start()) { - installMethod(result); - } - } - stats.finish(method, installedCode); - if (result != null) { - return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize()); - } - return null; + return compilation.execute(); } catch (BailoutException bailout) { BAILOUTS.increment(); if (ExitVMOnBailout.getValue(options)) { @@ -319,8 +409,9 @@ try { int compiledBytecodes = 0; int codeSize = 0; - if (result != null) { - compiledBytecodes = result.getBytecodeSize(); + + if (compilation.result != null) { + compiledBytecodes = compilation.result.getBytecodeSize(); CompiledBytecodes.add(compiledBytecodes); if (installedCode != null) { codeSize = installedCode.getSize(); @@ -334,7 +425,7 @@ compilationEvent.setMethod(method.format("%H.%n(%p)")); compilationEvent.setCompileId(getId()); compilationEvent.setCompileLevel(config.compilationLevelFullOptimization); - compilationEvent.setSucceeded(result != null && installedCode != null); + compilationEvent.setSucceeded(compilation.result != null && installedCode != null); compilationEvent.setIsOsr(isOSR); compilationEvent.setCodeSize(codeSize); compilationEvent.setInlinedBytes(compiledBytecodes); @@ -387,7 +478,7 @@ installedCode = null; Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult}; try (Scope s = Debug.scope("CodeInstall", context)) { - HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(getRequest().getMethod(), getRequest(), compResult); + HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, getRequest().getMethod(), getRequest(), compResult); installedCode = (HotSpotInstalledCode) codeCache.installCode(getRequest().getMethod(), compiledCode, null, getRequest().getMethod().getSpeculationLog(), installAsDefault); } catch (Throwable e) { throw Debug.handle(e);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Thu Apr 06 23:01:27 2017 +0000 @@ -267,7 +267,31 @@ public final int secondarySuperCacheOffset = getFieldOffset("Klass::_secondary_super_cache", Integer.class, "Klass*"); public final int secondarySupersOffset = getFieldOffset("Klass::_secondary_supers", Integer.class, "Array<Klass*>*"); - public final int classMirrorOffset = getFieldOffset("Klass::_java_mirror", Integer.class, "oop"); + public final boolean classMirrorIsHandle; + public final int classMirrorOffset; + { + String name = "Klass::_java_mirror"; + int offset = -1; + boolean isHandle = false; + try { + offset = getFieldOffset(name, Integer.class, "oop"); + } catch (JVMCIError e) { + + } + if (offset == -1) { + try { + offset = getFieldOffset(name, Integer.class, "jobject"); + isHandle = true; + } catch (JVMCIError e) { + + } + } + if (offset == -1) { + throw new JVMCIError("cannot get offset of field " + name + " with type oop or jobject"); + } + classMirrorOffset = offset; + classMirrorIsHandle = isHandle; + } public final int klassSuperKlassOffset = getFieldOffset("Klass::_super", Integer.class, "Klass*"); public final int klassModifierFlagsOffset = getFieldOffset("Klass::_modifier_flags", Integer.class, "jint");
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Thu Apr 06 23:01:27 2017 +0000 @@ -406,7 +406,7 @@ @Override public CompiledCode createCompiledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compResult) { HotSpotCompilationRequest compRequest = compilationRequest instanceof HotSpotCompilationRequest ? (HotSpotCompilationRequest) compilationRequest : null; - return HotSpotCompiledCodeBuilder.createCompiledCode(method, compRequest, compResult); + return HotSpotCompiledCodeBuilder.createCompiledCode(getCodeCache(), method, compRequest, compResult); } @Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java Thu Apr 06 23:01:27 2017 +0000 @@ -42,6 +42,7 @@ import org.graalvm.compiler.code.SourceMapping; import org.graalvm.compiler.graph.NodeSourcePosition; +import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.DebugInfo; import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.code.site.ConstantReference; @@ -61,13 +62,13 @@ public class HotSpotCompiledCodeBuilder { - public static HotSpotCompiledCode createCompiledCode(ResolvedJavaMethod method, HotSpotCompilationRequest compRequest, CompilationResult compResult) { + public static HotSpotCompiledCode createCompiledCode(CodeCacheProvider codeCache, ResolvedJavaMethod method, HotSpotCompilationRequest compRequest, CompilationResult compResult) { String name = compResult.getName(); byte[] targetCode = compResult.getTargetCode(); int targetCodeSize = compResult.getTargetCodeSize(); - Site[] sites = getSortedSites(compResult); + Site[] sites = getSortedSites(codeCache, compResult); Assumption[] assumptions = compResult.getAssumptions(); @@ -201,7 +202,7 @@ * {@code DebugInformationRecorder::add_new_pc_offset}). In addition, it expects * {@link Infopoint} PCs to be unique. */ - private static Site[] getSortedSites(CompilationResult target) { + private static Site[] getSortedSites(CodeCacheProvider codeCache, CompilationResult target) { List<Site> sites = new ArrayList<>( target.getExceptionHandlers().size() + target.getInfopoints().size() + target.getDataPatches().size() + target.getMarks().size() + target.getSourceMappings().size()); sites.addAll(target.getExceptionHandlers()); @@ -214,9 +215,11 @@ * can really be represented and recording the end PC seems to give the best results and * corresponds with what C1 and C2 do. */ - for (SourceMapping source : target.getSourceMappings()) { - sites.add(new Infopoint(source.getEndOffset(), new DebugInfo(source.getSourcePosition()), InfopointReason.BYTECODE_POSITION)); - assert verifySourcePositionReceivers(source.getSourcePosition()); + if (codeCache.shouldDebugNonSafepoints()) { + for (SourceMapping source : target.getSourceMappings()) { + sites.add(new Infopoint(source.getEndOffset(), new DebugInfo(source.getSourcePosition()), InfopointReason.BYTECODE_POSITION)); + assert verifySourcePositionReceivers(source.getSourcePosition()); + } } SiteComparator c = new SiteComparator();
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java Thu Apr 06 23:01:27 2017 +0000 @@ -71,8 +71,8 @@ VirtualStackSlot slot = lockStack.makeLockSlot(lockDepth); ValueNode lock = state.lockAt(lockIndex); JavaValue object = toJavaValue(lock); - boolean eliminated = object instanceof VirtualObject || state.monitorIdAt(lockIndex) == null; - assert state.monitorIdAt(lockIndex) == null || state.monitorIdAt(lockIndex).getLockDepth() == lockDepth; + boolean eliminated = object instanceof VirtualObject || state.monitorIdAt(lockIndex).isEliminated(); + assert state.monitorIdAt(lockIndex).getLockDepth() == lockDepth; return new StackLockValue(object, slot, eliminated); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java Thu Apr 06 23:01:27 2017 +0000 @@ -24,6 +24,7 @@ import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; + import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.Formattable; @@ -98,6 +99,9 @@ @Override @SuppressWarnings("try") public CompilationRequestResult compileMethod(CompilationRequest request) { + if (graalRuntime.isShutdown()) { + return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), false); + } OptionValues options = graalRuntime.getOptions(); if (graalRuntime.isBootstrapping()) { if (GraalDebugConfig.Options.BootstrapInitializeOnly.getValue(options)) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java Thu Apr 06 23:01:27 2017 +0000 @@ -45,6 +45,7 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFactory { private static MethodFilter[] graalCompileOnlyFilter; + private static boolean compileGraalWithC1Only; private final HotSpotGraalJVMCIServiceLocator locator; @@ -67,18 +68,17 @@ JVMCIVersionCheck.check(false); assert options == null : "cannot select " + getClass() + " service more than once"; options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS; - initializeGraalCompileOnlyFilter(options); - if (graalCompileOnlyFilter != null || !Options.UseTrivialPrefixes.getValue(options)) { - /* - * Exercise this code path early to encourage loading now. This doesn't solve problem of - * deadlock during class loading but seems to eliminate it in practice. - */ - adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization); - adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple); - } + initializeGraalCompilePolicyFields(options); + /* + * Exercise this code path early to encourage loading now. This doesn't solve problem of + * deadlock during class loading but seems to eliminate it in practice. + */ + adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization); + adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple); } - private static void initializeGraalCompileOnlyFilter(OptionValues options) { + private static void initializeGraalCompilePolicyFields(OptionValues options) { + compileGraalWithC1Only = Options.CompileGraalWithC1Only.getValue(options); String optionValue = Options.GraalCompileOnly.getValue(options); if (optionValue != null) { MethodFilter[] filter = MethodFilter.parse(optionValue); @@ -101,9 +101,6 @@ @Option(help = "In tiered mode compile Graal and JVMCI using optimized first tier code.", type = OptionType.Expert) public static final OptionKey<Boolean> CompileGraalWithC1Only = new OptionKey<>(true); - @Option(help = "Hook into VM-level mechanism for denoting compilations to be performed in first tier.", type = OptionType.Expert) - public static final OptionKey<Boolean> UseTrivialPrefixes = new OptionKey<>(false); - @Option(help = "A method filter selecting what should be compiled by Graal. All other requests will be reduced to CompilationLevel.Simple.", type = OptionType.Expert) public static final OptionKey<String> GraalCompileOnly = new OptionKey<>(null); // @formatter:on @@ -137,27 +134,15 @@ } @Override - public String[] getTrivialPrefixes() { - if (Options.UseTrivialPrefixes.getValue(options)) { - if (Options.CompileGraalWithC1Only.getValue(options)) { - return new String[]{"jdk/vm/ci", "org/graalvm/compiler", "com/oracle/graal"}; - } - } - return null; - } - - @Override public CompilationLevelAdjustment getCompilationLevelAdjustment() { if (graalCompileOnlyFilter != null) { return CompilationLevelAdjustment.ByFullSignature; } - if (!Options.UseTrivialPrefixes.getValue(options)) { - if (Options.CompileGraalWithC1Only.getValue(options)) { - // We only decide using the class declaring the method - // so no need to have the method name and signature - // symbols converted to a String. - return CompilationLevelAdjustment.ByHolder; - } + if (compileGraalWithC1Only) { + // We only decide using the class declaring the method + // so no need to have the method name and signature + // symbols converted to a String. + return CompilationLevelAdjustment.ByHolder; } return CompilationLevelAdjustment.None; } @@ -193,10 +178,12 @@ return CompilationLevel.Simple; } } - if (level.ordinal() > CompilationLevel.Simple.ordinal()) { - String declaringClassName = declaringClass.getName(); - if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm.compiler") || declaringClassName.startsWith("com.oracle.graal")) { - return CompilationLevel.Simple; + if (compileGraalWithC1Only) { + if (level.ordinal() > CompilationLevel.Simple.ordinal()) { + String declaringClassName = declaringClass.getName(); + if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm") || declaringClassName.startsWith("com.oracle.graal")) { + return CompilationLevel.Simple; + } } } return level;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java Thu Apr 06 23:01:27 2017 +0000 @@ -30,68 +30,77 @@ import org.graalvm.compiler.serviceprovider.ServiceProvider; import jdk.vm.ci.hotspot.HotSpotVMEventListener; -import jdk.vm.ci.runtime.JVMCICompiler; import jdk.vm.ci.runtime.JVMCICompilerFactory; import jdk.vm.ci.services.JVMCIServiceLocator; +import jdk.vm.ci.services.Services; @ServiceProvider(JVMCIServiceLocator.class) public final class HotSpotGraalJVMCIServiceLocator extends JVMCIServiceLocator { - private boolean exportsAdded; + /** + * 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(); - /** - * Dynamically exports and opens various internal JDK packages to the Graal module. This - * requires only a single {@code --add-exports=java.base/jdk.internal.module=<Graal module>} on - * the VM command line instead of a {@code --add-exports} instance for each JDK internal package - * used by Graal. - */ - private void addExports() { - if (JAVA_SPECIFICATION_VERSION >= 9 && !exportsAdded) { - Object javaBaseModule = getModule.invoke(String.class); - Object graalModule = getModule.invoke(getClass()); - addExports.invokeStatic(javaBaseModule, "jdk.internal.misc", graalModule); - addExports.invokeStatic(javaBaseModule, "jdk.internal.jimage", graalModule); - addExports.invokeStatic(javaBaseModule, "com.sun.crypto.provider", graalModule); - addOpens.invokeStatic(javaBaseModule, "jdk.internal.misc", graalModule); - addOpens.invokeStatic(javaBaseModule, "jdk.internal.jimage", graalModule); - addOpens.invokeStatic(javaBaseModule, "com.sun.crypto.provider", graalModule); - exportsAdded = true; + private boolean exportsAdded; + + /** + * Dynamically exports and opens various internal JDK packages to the Graal module. This + * requires only a single {@code --add-exports=java.base/jdk.internal.module=<Graal module>} + * on the VM command line instead of a {@code --add-exports} instance for each JDK internal + * package used by Graal. + */ + private void addExports() { + if (JAVA_SPECIFICATION_VERSION >= 9 && !exportsAdded) { + Object javaBaseModule = getModule.invoke(String.class); + Object graalModule = getModule.invoke(getClass()); + addExports.invokeStatic(javaBaseModule, "jdk.internal.misc", graalModule); + addExports.invokeStatic(javaBaseModule, "jdk.internal.jimage", graalModule); + addExports.invokeStatic(javaBaseModule, "com.sun.crypto.provider", graalModule); + addOpens.invokeStatic(javaBaseModule, "jdk.internal.misc", graalModule); + addOpens.invokeStatic(javaBaseModule, "jdk.internal.jimage", graalModule); + addOpens.invokeStatic(javaBaseModule, "com.sun.crypto.provider", graalModule); + exportsAdded = true; + } + } + + <T> T getProvider(Class<T> service, HotSpotGraalJVMCIServiceLocator locator) { + if (service == JVMCICompilerFactory.class) { + addExports(); + return service.cast(new HotSpotGraalCompilerFactory(locator)); + } else if (service == HotSpotVMEventListener.class) { + if (graalRuntime != null) { + addExports(); + return service.cast(new HotSpotGraalVMEventListener(graalRuntime)); + } + } + return null; + } + + private HotSpotGraalRuntime graalRuntime; + + /** + * Notifies this object of the compiler created via {@link HotSpotGraalJVMCIServiceLocator}. + */ + void onCompilerCreation(HotSpotGraalCompiler compiler) { + assert this.graalRuntime == null : "only expect a single JVMCICompiler to be created"; + this.graalRuntime = (HotSpotGraalRuntime) compiler.getGraalRuntime(); } } - private HotSpotGraalRuntime graalRuntime; - @Override public <T> T getProvider(Class<T> service) { - if (service == JVMCICompilerFactory.class) { - addExports(); - return service.cast(new HotSpotGraalCompilerFactory(this)); - } else if (service == HotSpotVMEventListener.class) { - if (graalRuntime != null) { - addExports(); - return service.cast(new HotSpotGraalVMEventListener(graalRuntime)); - } - } - return null; + return Shared.SINGLETON.getProvider(service, this); } /** - * The signature cannot mention HotSpotGraalCompiler since it indirectly references - * JVMCICompiler which is in a non-exported JVMCI package. This causes an IllegalAccessError - * while looking for the - * <a href="http://hg.openjdk.java.net/jdk9/hs/jdk/rev/89ef4b822745#l32.65">provider</a> factory - * method: - * - * <pre> - * java.util.ServiceConfigurationError: jdk.vm.ci.services.JVMCIServiceLocator: Unable to get public provider() method - * ... - * Caused by: java.lang.IllegalAccessError: superinterface check failed: class org.graalvm.compiler.api.runtime.GraalJVMCICompiler - * (in module org.graalvm.compiler.graal_core) cannot access class jdk.vm.ci.runtime.JVMCICompiler (in module jdk.vm.ci) because - * module jdk.vm.ci does not export jdk.vm.ci.runtime to module org.graalvm.compiler.graal_core - * </pre> + * Notifies this object of the compiler created via {@link HotSpotGraalJVMCIServiceLocator}. */ - void onCompilerCreation(JVMCICompiler compiler) { - assert this.graalRuntime == null : "only expect a single JVMCICompiler to be created"; - this.graalRuntime = (HotSpotGraalRuntime) ((HotSpotGraalCompiler) compiler).getGraalRuntime(); + @SuppressWarnings("static-method") + void onCompilerCreation(HotSpotGraalCompiler compiler) { + Shared.SINGLETON.onCompilerCreation(compiler); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Thu Apr 06 23:01:27 2017 +0000 @@ -34,8 +34,22 @@ import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodFilter; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Verify; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.zip.Deflater; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.runtime.GraalRuntime; @@ -278,6 +292,7 @@ } private long runtimeStartTime; + private boolean shutdown; /** * Take action related to entering a new execution phase. @@ -291,6 +306,7 @@ } void shutdown() { + shutdown = true; if (debugValuesPrinter != null) { debugValuesPrinter.printDebugValues(options); } @@ -302,6 +318,8 @@ } } BenchmarkCounters.shutdown(runtime(), options, runtimeStartTime); + + archiveAndDeleteOutputDirectory(); } void clearMeters() { @@ -321,4 +339,95 @@ public boolean isBootstrapping() { return bootstrapJVMCI && !bootstrapFinished; } + + @Override + public boolean isShutdown() { + return shutdown; + } + + /** + * Gets a unique identifier for this execution such as a process ID. + */ + private static String getExecutionID() { + String runtimeName = ManagementFactory.getRuntimeMXBean().getName(); + try { + int index = runtimeName.indexOf('@'); + if (index != -1) { + long pid = Long.parseLong(runtimeName.substring(0, index)); + return Long.toString(pid); + } + } catch (NumberFormatException e) { + } + return runtimeName; + } + + private String outputDirectory; + + @Override + public String getOutputDirectory() { + if (outputDirectory == null) { + outputDirectory = "graal_output_" + getExecutionID(); + File dir = new File(outputDirectory).getAbsoluteFile(); + if (!dir.exists()) { + dir.mkdirs(); + if (!dir.exists()) { + TTY.println("Warning: could not create Graal diagnostic directory " + dir); + return null; + } + } + } + return outputDirectory; + } + + /** + * Archives and deletes the {@linkplain #getOutputDirectory() output directory} if it exists. + */ + private void archiveAndDeleteOutputDirectory() { + if (outputDirectory != null) { + Path dir = Paths.get(outputDirectory); + if (dir.toFile().exists()) { + try { + // Give compiler threads a chance to finishing dumping + Thread.sleep(1000); + } catch (InterruptedException e1) { + } + File zip = new File(outputDirectory + ".zip").getAbsoluteFile(); + List<Path> toDelete = new ArrayList<>(); + try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip))) { + zos.setLevel(Deflater.BEST_COMPRESSION); + Files.walkFileTree(dir, Collections.emptySet(), Integer.MAX_VALUE, new SimpleFileVisitor<Path>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if (attrs.isRegularFile()) { + ZipEntry ze = new ZipEntry(file.toString()); + zos.putNextEntry(ze); + zos.write(Files.readAllBytes(file)); + zos.closeEntry(); + } + toDelete.add(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path d, IOException exc) throws IOException { + toDelete.add(d); + return FileVisitResult.CONTINUE; + } + }); + TTY.println("Graal diagnostic output saved in %s", zip); + } catch (IOException e) { + TTY.printf("IO error archiving %s:%n", dir); + e.printStackTrace(TTY.out); + } + for (Path p : toDelete) { + try { + Files.delete(p); + } catch (IOException e) { + TTY.printf("IO error deleting %s:%n", p); + e.printStackTrace(TTY.out); + } + } + } + } + } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java Thu Apr 06 23:01:27 2017 +0000 @@ -62,4 +62,19 @@ * Determines if the VM is currently bootstrapping the JVMCI compiler. */ boolean isBootstrapping(); + + /** + * This runtime has been requested to shutdown. + */ + boolean isShutdown(); + + /** + * Gets a directory into which diagnostics such crash reports and dumps should be written. This + * method will create the directory if it doesn't exist so it should only be called if + * diagnostics are about to be generated. + * + * @return the directory into which diagnostics can be written or {@code null} if the directory + * does not exist and could not be created + */ + String getOutputDirectory(); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java Thu Apr 06 23:01:27 2017 +0000 @@ -46,10 +46,10 @@ @Override public void notifyInstall(HotSpotCodeCacheProvider codeCache, InstalledCode installedCode, CompiledCode compiledCode) { - if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) { + if (Debug.isDumpEnabled(Debug.BASIC_LEVEL)) { CompilationResult compResult = Debug.contextLookup(CompilationResult.class); assert compResult != null : "can't dump installed code properly without CompilationResult"; - Debug.dump(Debug.BASIC_LOG_LEVEL, installedCode, "After code installation"); + Debug.dump(Debug.BASIC_LEVEL, installedCode, "After code installation"); } if (Debug.isLogEnabled()) { Debug.log("%s", codeCache.disassemble(installedCode));
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java Thu Apr 06 23:01:27 2017 +0000 @@ -45,7 +45,7 @@ } /** - * Replace any instance of %p with a an identifying name. Try to get it from the RuntimeMXBean + * Replace any instance of %p with an identifying name. Try to get it from the RuntimeMXBean * name. * * @return the name of the file to log to
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Thu Apr 06 23:01:27 2017 +0000 @@ -31,6 +31,7 @@ import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_KLASS_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_HANDLE_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.COMPRESSED_HUB_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.DISPLACED_MARK_WORD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_LOCATION; @@ -40,6 +41,7 @@ import java.lang.ref.Reference; import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; @@ -409,10 +411,17 @@ return; } + ValueNode hub = n.getHub(); + GraalHotSpotVMConfig vmConfig = runtime.getVMConfig(); StructuredGraph graph = n.graph(); - assert !n.getHub().isConstant(); - AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getVMConfig().classMirrorOffset); - FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, n.stamp(), null, BarrierType.NONE)); + assert !hub.isConstant() || GraalOptions.ImmutableCode.getValue(graph.getOptions()); + AddressNode mirrorAddress = createOffsetAddress(graph, hub, vmConfig.classMirrorOffset); + FloatingReadNode read = graph.unique(new FloatingReadNode(mirrorAddress, CLASS_MIRROR_LOCATION, null, vmConfig.classMirrorIsHandle ? StampFactory.forKind(target.wordJavaKind) : n.stamp(), + null, BarrierType.NONE)); + if (vmConfig.classMirrorIsHandle) { + AddressNode address = createOffsetAddress(graph, read, 0); + read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_HANDLE_LOCATION, null, n.stamp(), null, BarrierType.NONE)); + } n.replaceAtUsagesAndDelete(read); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Thu Apr 06 23:01:27 2017 +0000 @@ -323,7 +323,8 @@ */ private static ValueNode getMetaspaceConstantPool(GraphBuilderContext b, ValueNode constantPoolOop, WordTypes wordTypes, GraalHotSpotVMConfig config) { // ConstantPool.constantPoolOop is in fact the holder class. - ClassGetHubNode klass = b.add(new ClassGetHubNode(b.nullCheckedValue(constantPoolOop, DeoptimizationAction.None))); + ValueNode value = b.nullCheckedValue(constantPoolOop, DeoptimizationAction.None); + ValueNode klass = b.add(ClassGetHubNode.create(value, b.getMetaAccess(), b.getConstantReflection(), false)); boolean notCompressible = false; AddressNode constantsAddress = b.add(new OffsetAddressNode(klass, b.add(ConstantNode.forLong(config.instanceKlassConstantsOffset))));
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java Thu Apr 06 23:01:27 2017 +0000 @@ -90,7 +90,7 @@ if (ImmutableCode.getValue(options)) { // lowering introduces class constants, therefore it must be after lowering - ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config.classMirrorOffset, config.useCompressedOops ? config.getOopEncoding() : null)); + ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config)); if (VerifyPhases.getValue(options)) { ret.getHighTier().appendPhase(new AheadOfTimeVerificationPhase()); } @@ -146,10 +146,10 @@ protected void run(StructuredGraph graph, HighTierContext context) { EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, runtime.getTarget().arch); - SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(context.getMetaAccess(), context.getConstantReflection(), context.getConstantFieldProvider(), - context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions()), runtime.getTarget().arch); StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), AllowAssumptions.YES).method(graph.method()).build(); - graphDecoder.decode(targetGraph, encodedGraph); + SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context.getMetaAccess(), context.getConstantReflection(), + context.getConstantFieldProvider(), context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions())); + graphDecoder.decode(encodedGraph); } @Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java Thu Apr 06 23:01:27 2017 +0000 @@ -109,7 +109,7 @@ PointerEqualsNode comparison = b.add(new PointerEqualsNode(left, right)); ValueNode eqValue = b.add(forBoolean(opcode == POINTER_EQ)); ValueNode neValue = b.add(forBoolean(opcode == POINTER_NE)); - b.addPush(returnKind, new ConditionalNode(comparison, eqValue, neValue)); + b.addPush(returnKind, ConditionalNode.create(comparison, eqValue, neValue)); break; case IS_NULL: @@ -118,7 +118,7 @@ assert pointer.stamp() instanceof MetaspacePointerStamp; LogicNode isNull = b.add(IsNullNode.create(pointer)); - b.addPush(returnKind, new ConditionalNode(isNull, b.add(forBoolean(true)), b.add(forBoolean(false)))); + b.addPush(returnKind, ConditionalNode.create(isNull, b.add(forBoolean(true)), b.add(forBoolean(false)))); break; case FROM_POINTER:
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -29,6 +29,7 @@ import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -72,8 +73,8 @@ * @param config * @param markId id of the config value */ - public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config, int markId) { - super(TYPE, StampFactory.forNodeIntrinsic()); + public GraalHotSpotVMConfigNode(@InjectedNodeParameter Stamp stamp, @InjectedNodeParameter GraalHotSpotVMConfig config, int markId) { + super(TYPE, stamp); this.config = config; this.markId = markId; } @@ -85,7 +86,7 @@ * @param markId id of the config value * @param kind explicit type of the node */ - public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config, int markId, JavaKind kind) { + public GraalHotSpotVMConfigNode(GraalHotSpotVMConfig config, int markId, JavaKind kind) { super(TYPE, StampFactory.forKind(kind)); this.config = config; this.markId = markId; @@ -100,13 +101,13 @@ @NodeIntrinsic private static native boolean areConfigValuesConstant(); - @NodeIntrinsic(setStampFromReturnType = true) + @NodeIntrinsic private static native long loadLongConfigValue(@ConstantNodeParameter int markId); - @NodeIntrinsic(setStampFromReturnType = true) + @NodeIntrinsic private static native int loadIntConfigValue(@ConstantNodeParameter int markId); - @NodeIntrinsic(setStampFromReturnType = true) + @NodeIntrinsic private static native byte loadByteConfigValue(@ConstantNodeParameter int markId); public static long cardTableAddress() {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -32,7 +32,7 @@ import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; -import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil; @@ -44,7 +44,6 @@ import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.Value; /** @@ -59,8 +58,8 @@ protected final ForeignCallDescriptor descriptor; - public StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { - super(TYPE, StampFactory.forKind(JavaKind.fromJavaClass(descriptor.getResultType()))); + public StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, @InjectedNodeParameter Stamp stamp, ForeignCallDescriptor descriptor, ValueNode... arguments) { + super(TYPE, stamp); this.arguments = new NodeInputList<>(this, arguments); this.descriptor = descriptor; this.foreignCalls = foreignCalls;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -44,8 +45,8 @@ @OptionalInput protected ValueNode value; - public EncodedSymbolNode(ValueNode value) { - super(TYPE, null); + public EncodedSymbolNode(@InjectedNodeParameter Stamp stamp, ValueNode value) { + super(TYPE, stamp); assert value != null; this.value = value; } @@ -61,6 +62,6 @@ return this; } - @NodeIntrinsic(setStampFromReturnType = true) + @NodeIntrinsic public static native Word encode(Object constant); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Thu Apr 06 23:01:27 2017 +0000 @@ -22,7 +22,6 @@ */ package org.graalvm.compiler.hotspot.phases; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_LOCATION; import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; import static org.graalvm.compiler.nodes.NamedLocationIdentity.FINAL_LOCATION; @@ -32,9 +31,11 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.CompressionNode; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp; +import org.graalvm.compiler.hotspot.replacements.HubGetClassNode; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -67,12 +68,10 @@ */ public class LoadJavaMirrorWithKlassPhase extends BasePhase<PhaseContext> { - private final int classMirrorOffset; private final CompressEncoding oopEncoding; - public LoadJavaMirrorWithKlassPhase(int classMirrorOffset, CompressEncoding oopEncoding) { - this.classMirrorOffset = classMirrorOffset; - this.oopEncoding = oopEncoding; + public LoadJavaMirrorWithKlassPhase(GraalHotSpotVMConfig config) { + this.oopEncoding = config.useCompressedOops ? config.getOopEncoding() : null; } private ValueNode getClassConstantReplacement(StructuredGraph graph, PhaseContext context, JavaConstant constant) { @@ -85,13 +84,12 @@ if (type instanceof HotSpotResolvedObjectType) { ConstantNode klass = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) type).klass(), metaAccess, graph); - AddressNode address = graph.unique(new OffsetAddressNode(klass, ConstantNode.forLong(classMirrorOffset, graph))); - ValueNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, stamp)); + ValueNode getClass = graph.unique(new HubGetClassNode(metaAccess, klass)); if (((HotSpotObjectConstant) constant).isCompressed()) { - return CompressionNode.compress(read, oopEncoding); + return CompressionNode.compress(getClass, oopEncoding); } else { - return read; + return getClass; } } else { /*
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java Thu Apr 06 23:01:27 2017 +0000 @@ -94,7 +94,7 @@ assert graph.getNodes(EntryMarkerNode.TYPE).isEmpty(); return; } - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement initial at bci %d", graph.getEntryBCI()); + Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement initial at bci %d", graph.getEntryBCI()); EntryMarkerNode osr; int maxIterations = -1; @@ -144,7 +144,7 @@ proxy.replaceAndDelete(proxy.value()); } GraphUtil.removeFixedWithUnusedInputs(osr); - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement loop peeling result"); + Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement loop peeling result"); } while (true); FrameState osrState = osr.stateAfter(); @@ -157,7 +157,7 @@ graph.setStart(osrStart); osrStart.setStateAfter(osrState); - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement after setting OSR start"); + Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement after setting OSR start"); final int localsSize = osrState.localsSize(); final int locksSize = osrState.locksSize(); @@ -188,9 +188,9 @@ } osr.replaceAtUsages(InputType.Guard, osrStart); - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement after replacing entry proxies"); + Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement after replacing entry proxies"); GraphUtil.killCFG(start); - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement result"); + Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement result"); new DeadCodeEliminationPhase(Required).apply(graph); if (currentOSRWithLocks) { @@ -210,7 +210,7 @@ osrMonitorEnter.setNext(oldNext); osrStart.setNext(osrMonitorEnter); } - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "After inserting OSR monitor enters"); + Debug.dump(Debug.DETAILED_LEVEL, graph, "After inserting OSR monitor enters"); /* * Ensure balanced monitorenter - monitorexit * @@ -226,7 +226,7 @@ } } } - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement result"); + Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement result"); new DeadCodeEliminationPhase(Required).apply(graph); /* * There must not be any parameter nodes left after OSR compilation.
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java Thu Apr 06 23:01:27 2017 +0000 @@ -28,9 +28,6 @@ import java.util.HashMap; import java.util.Map.Entry; -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.meta.JavaConstant; - import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; @@ -43,6 +40,9 @@ import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; +import jdk.vm.ci.meta.Constant; + public class EliminateRedundantInitializationPhase extends BasePhase<PhaseContext> { /** * Find blocks with class initializing nodes for the class identified the by the constant node. @@ -204,7 +204,7 @@ ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, true, false); ArrayList<Node> redundantInits = new ArrayList<>(); for (ConstantNode node : getConstantNodes(graph)) { - JavaConstant constant = node.asJavaConstant(); + Constant constant = node.asConstant(); if (constant instanceof HotSpotMetaspaceConstant) { redundantInits.addAll(processConstantNode(cfg, node)); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -25,8 +25,11 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -42,6 +45,7 @@ import org.graalvm.compiler.nodes.extended.GetClassNode; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.spi.Lowerable; @@ -69,19 +73,30 @@ this.clazz = clazz; } - @Override - public Node canonical(CanonicalizerTool tool) { - if (tool.allUsagesAvailable() && hasNoUsages()) { + public static ValueNode create(ValueNode clazz, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean allUsagesAvailable) { + return canonical(null, metaAccess, constantReflection, allUsagesAvailable, KlassPointerStamp.klass(), clazz); + } + + @SuppressWarnings("unused") + public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode clazz) { + ValueNode clazzValue = create(clazz, b.getMetaAccess(), b.getConstantReflection(), false); + b.push(JavaKind.Object, b.recursiveAppend(clazzValue)); + return true; + } + + public static ValueNode canonical(ClassGetHubNode classGetHubNode, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean allUsagesAvailable, Stamp stamp, + ValueNode clazz) { + ClassGetHubNode self = classGetHubNode; + if (allUsagesAvailable && self != null && self.hasNoUsages()) { return null; } else { if (clazz.isConstant()) { - MetaAccessProvider metaAccess = tool.getMetaAccess(); if (metaAccess != null) { - ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(clazz.asJavaConstant()); + ResolvedJavaType exactType = constantReflection.asJavaType(clazz.asJavaConstant()); if (exactType.isPrimitive()) { - return ConstantNode.forConstant(stamp(), JavaConstant.NULL_POINTER, metaAccess); + return ConstantNode.forConstant(stamp, JavaConstant.NULL_POINTER, metaAccess); } else { - return ConstantNode.forConstant(stamp(), tool.getConstantReflection().asObjectHub(exactType), metaAccess); + return ConstantNode.forConstant(stamp, constantReflection.asObjectHub(exactType), metaAccess); } } } @@ -90,14 +105,22 @@ return new LoadHubNode(KlassPointerStamp.klassNonNull(), getClass.getObject()); } if (clazz instanceof HubGetClassNode) { - // replace _klass._java_mirror._klass -> _klass + // Replace: _klass._java_mirror._klass -> _klass return ((HubGetClassNode) clazz).getHub(); } - return this; + if (self == null) { + self = new ClassGetHubNode(clazz); + } + return self; } } @Override + public Node canonical(CanonicalizerTool tool) { + return canonical(this, tool.getMetaAccess(), tool.getConstantReflection(), tool.allUsagesAvailable(), stamp(), clazz); + } + + @Override public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Thu Apr 06 23:01:27 2017 +0000 @@ -702,17 +702,17 @@ public static Word loadWordFromObject(Object object, int offset) { ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject"); - return loadWordFromObjectIntrinsic(object, offset, getWordKind(), LocationIdentity.any()); + return loadWordFromObjectIntrinsic(object, offset, LocationIdentity.any(), getWordKind()); } public static Word loadWordFromObject(Object object, int offset, LocationIdentity identity) { ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject"); - return loadWordFromObjectIntrinsic(object, offset, getWordKind(), identity); + return loadWordFromObjectIntrinsic(object, offset, identity, getWordKind()); } public static KlassPointer loadKlassFromObject(Object object, int offset, LocationIdentity identity) { ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject"); - return loadKlassFromObjectIntrinsic(object, offset, getWordKind(), identity); + return loadKlassFromObjectIntrinsic(object, offset, identity, getWordKind()); } /** @@ -725,17 +725,17 @@ return registerAsWord(register, true, false); } - @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = ReadRegisterNode.class) public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming); - @NodeIntrinsic(value = WriteRegisterNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = WriteRegisterNode.class) public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value); - @NodeIntrinsic(value = RawLoadNode.class, setStampFromReturnType = true) - private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity); + @NodeIntrinsic(value = RawLoadNode.class) + private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter JavaKind wordKind); - @NodeIntrinsic(value = RawLoadNode.class, setStampFromReturnType = true) - private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity); + @NodeIntrinsic(value = RawLoadNode.class) + private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter JavaKind wordKind); @NodeIntrinsic(value = LoadHubNode.class) public static native KlassPointer loadHubIntrinsic(Object object); @@ -803,6 +803,8 @@ public static final LocationIdentity CLASS_MIRROR_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror"); + public static final LocationIdentity CLASS_MIRROR_HANDLE_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror handle"); + public static final LocationIdentity HEAP_TOP_LOCATION = NamedLocationIdentity.mutable("HeapTop"); @Fold
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -25,6 +25,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.graph.Node; @@ -70,7 +71,7 @@ return null; } else { MetaAccessProvider metaAccess = tool.getMetaAccess(); - if (metaAccess != null && hub.isConstant()) { + if (metaAccess != null && hub.isConstant() && !GraalOptions.ImmutableCode.getValue(graph().getOptions())) { ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(hub.asConstant()); if (exactType != null) { return ConstantNode.forConstant(tool.getConstantReflection().asJavaClass(exactType), metaAccess);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -25,6 +25,9 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -38,6 +41,7 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -63,6 +67,18 @@ this.klass = klass; } + public static ValueNode create(GraalHotSpotVMConfig config, ValueNode klass, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess) { + Stamp stamp = StampFactory.forKind(JavaKind.Int); + return canonical(null, config, klass, stamp, constantReflection, metaAccess); + } + + @SuppressWarnings("unused") + public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, @InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass) { + ValueNode valueNode = create(config, klass, b.getConstantReflection(), b.getMetaAccess()); + b.push(JavaKind.Int, b.recursiveAppend(valueNode)); + return true; + } + @Override public boolean inferStamp() { if (klass instanceof LoadHubNode) { @@ -92,27 +108,36 @@ if (tool.allUsagesAvailable() && hasNoUsages()) { return null; } else { - if (klass.isConstant()) { - if (!klass.asConstant().isDefaultForKind()) { - Constant constant = stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), klass.asConstant(), config.klassLayoutHelperOffset); - return ConstantNode.forConstant(stamp(), constant, tool.getMetaAccess()); + return canonical(this, config, klass, stamp(), tool.getConstantReflection(), tool.getMetaAccess()); + } + } + + private static ValueNode canonical(KlassLayoutHelperNode klassLayoutHelperNode, GraalHotSpotVMConfig config, ValueNode klass, Stamp stamp, ConstantReflectionProvider constantReflection, + MetaAccessProvider metaAccess) { + KlassLayoutHelperNode self = klassLayoutHelperNode; + if (klass.isConstant()) { + if (!klass.asConstant().isDefaultForKind()) { + Constant constant = stamp.readConstant(constantReflection.getMemoryAccessProvider(), klass.asConstant(), config.klassLayoutHelperOffset); + return ConstantNode.forConstant(stamp, constant, metaAccess); + } + } + if (klass instanceof LoadHubNode) { + LoadHubNode hub = (LoadHubNode) klass; + Stamp hubStamp = hub.getValue().stamp(); + if (hubStamp instanceof ObjectStamp) { + ObjectStamp ostamp = (ObjectStamp) hubStamp; + HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) ostamp.type(); + if (type != null && type.isArray() && !type.getComponentType().isPrimitive()) { + // The layout for all object arrays is the same. + Constant constant = stamp.readConstant(constantReflection.getMemoryAccessProvider(), type.klass(), config.klassLayoutHelperOffset); + return ConstantNode.forConstant(stamp, constant, metaAccess); } } - if (klass instanceof LoadHubNode) { - LoadHubNode hub = (LoadHubNode) klass; - Stamp hubStamp = hub.getValue().stamp(); - if (hubStamp instanceof ObjectStamp) { - ObjectStamp ostamp = (ObjectStamp) hubStamp; - HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) ostamp.type(); - if (type != null && type.isArray() && !type.getComponentType().isPrimitive()) { - // The layout for all object arrays is the same. - Constant constant = stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), type.klass(), config.klassLayoutHelperOffset); - return ConstantNode.forConstant(stamp(), constant, tool.getMetaAccess()); - } - } - } - return this; } + if (self == null) { + self = new KlassLayoutHelperNode(config, klass); + } + return self; } @Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java Thu Apr 06 23:01:27 2017 +0000 @@ -35,8 +35,10 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; +import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.java.LoadExceptionObjectNode; @@ -52,6 +54,7 @@ import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.ResolvedJavaType; /** * Snippet for loading the exception object at the start of an exception dispatcher. @@ -76,15 +79,19 @@ public static class Templates extends AbstractTemplates { private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException", EXCEPTION_OOP_LOCATION, EXCEPTION_PC_LOCATION); + private final HotSpotWordTypes wordTypes; public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { super(options, providers, providers.getSnippetReflection(), target); + this.wordTypes = providers.getWordTypes(); } public void lower(LoadExceptionObjectNode loadExceptionObject, HotSpotRegistersProvider registers, LoweringTool tool) { StructuredGraph graph = loadExceptionObject.graph(); if (LoadExceptionObjectInVM.getValue(graph.getOptions())) { - ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), true, false)); + ResolvedJavaType wordType = providers.getMetaAccess().lookupJavaType(Word.class); + Stamp stamp = wordTypes.getWordStamp(wordType); + ReadRegisterNode thread = graph.add(new ReadRegisterNode(stamp, registers.getThreadRegister(), true, false)); graph.addBeforeFixed(loadExceptionObject, thread); ForeignCallNode loadExceptionC = graph.add(new ForeignCallNode(providers.getForeignCalls(), LOAD_AND_CLEAR_EXCEPTION, thread)); loadExceptionC.setStateAfter(loadExceptionObject.stateAfter());
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Thu Apr 06 23:01:27 2017 +0000 @@ -56,7 +56,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeTlabTop; import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileAllocations; import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileAllocationsContext; -import static org.graalvm.compiler.nodes.PiArrayNode.piArrayCast; +import static org.graalvm.compiler.nodes.PiArrayNode.piArrayCastToSnippetReplaceeStamp; import static org.graalvm.compiler.nodes.PiNode.piCastToSnippetReplaceeStamp; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY; @@ -226,7 +226,7 @@ return verifyOop(result); } - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object newInstance(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub); @Snippet @@ -307,7 +307,7 @@ @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { Object result = allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters); - return piArrayCast(verifyOop(result), length); + return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length); } private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, Register threadRegister, @@ -334,20 +334,20 @@ return result; } - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object newArray(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int length, boolean fillContents); public static final ForeignCallDescriptor DYNAMIC_NEW_ARRAY = new ForeignCallDescriptor("dynamic_new_array", Object.class, Class.class, int.class); public static final ForeignCallDescriptor DYNAMIC_NEW_INSTANCE = new ForeignCallDescriptor("dynamic_new_instance", Object.class, Class.class); - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object dynamicNewArrayStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType, int length); public static Object dynamicNewInstanceStub(Class<?> elementType) { return dynamicNewInstanceStubCall(DYNAMIC_NEW_INSTANCE, elementType); } - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object dynamicNewInstanceStubCall(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType); @Snippet @@ -396,7 +396,7 @@ int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG); Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", true, options, counters); - return piArrayCast(verifyOop(result), length); + return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length); } /** @@ -418,7 +418,7 @@ return newmultiarray(hubPIC, rank, dimensions); } - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object newArrayCall(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int rank, Word dims); /**
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ReflectionGetCallerClassNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ReflectionGetCallerClassNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -80,7 +80,7 @@ /** * If inlining is deep enough this method returns a {@link ConstantNode} of the caller class by - * walking the the stack. + * walking the stack. * * @param metaAccess * @return ConstantNode of the caller class, or null
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.hotspot.replacements.arraycopy; -import jdk.vm.ci.meta.JavaKind; - import static org.graalvm.compiler.core.common.LocationIdentity.any; import org.graalvm.compiler.core.common.LocationIdentity; @@ -33,11 +31,12 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.nodes.spi.Virtualizable; import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; +import jdk.vm.ci.meta.JavaKind; + @NodeInfo -public final class ArrayCopyNode extends BasicArrayCopyNode implements Virtualizable, Lowerable { +public final class ArrayCopyNode extends BasicArrayCopyNode implements Lowerable { public static final NodeClass<ArrayCopyNode> TYPE = NodeClass.create(ArrayCopyNode.class);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java Thu Apr 06 23:01:27 2017 +0000 @@ -63,6 +63,7 @@ import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.type.StampTool; +import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetCounter; import org.graalvm.compiler.replacements.SnippetCounter.Group; @@ -628,7 +629,7 @@ private void instantiate(Arguments args, BasicArrayCopyNode arraycopy) { StructuredGraph graph = arraycopy.graph(); SnippetTemplate template = template(args); - UnmodifiableEconomicMap<Node, Node> replacements = template.instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args); + UnmodifiableEconomicMap<Node, Node> replacements = template.instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args, false); for (Node originalNode : replacements.getKeys()) { if (originalNode instanceof Invoke) { Invoke invoke = (Invoke) replacements.get(originalNode); @@ -643,17 +644,18 @@ if (arraycopy.stateDuring() != null) { newInvoke.setStateDuring(arraycopy.stateDuring()); } else { - assert arraycopy.stateAfter() != null; + assert arraycopy.stateAfter() != null : arraycopy; newInvoke.setStateAfter(arraycopy.stateAfter()); } graph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke); } else if (originalNode instanceof ArrayCopySlowPathNode) { ArrayCopySlowPathNode slowPath = (ArrayCopySlowPathNode) replacements.get(originalNode); - assert arraycopy.stateAfter() != null; - slowPath.setStateAfter(arraycopy.stateAfter()); + assert arraycopy.stateAfter() != null : arraycopy; + assert slowPath.stateAfter() == arraycopy.stateAfter(); slowPath.setBci(arraycopy.getBci()); } } + GraphUtil.killCFG(arraycopy); } } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java Thu Apr 06 23:01:27 2017 +0000 @@ -157,6 +157,6 @@ public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_PC = newDescriptor(ExceptionHandlerStub.class, "exceptionHandlerForPc", Word.class, Word.class); - @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = StubForeignCallNode.class) public static native Word exceptionHandlerForPc(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForPc, Word thread); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java Thu Apr 06 23:01:27 2017 +0000 @@ -32,6 +32,7 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.debug.Debug; @@ -57,6 +58,7 @@ import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; import jdk.vm.ci.hotspot.HotSpotSignature; +import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaMethod; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.MetaAccessProvider; @@ -241,17 +243,13 @@ } kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result)); - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Initial stub graph"); - } + Debug.dump(Debug.VERBOSE_LEVEL, graph, "Initial stub graph"); kit.inlineInvokes(); new RemoveValueProxyPhase().apply(graph); - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Stub graph before compilation"); - } + Debug.dump(Debug.VERBOSE_LEVEL, graph, "Stub graph before compilation"); return graph; } @@ -269,13 +267,14 @@ } private StubForeignCallNode createTargetCall(GraphKit kit, ParameterNode[] params, ReadRegisterNode thread) { + Stamp stamp = StampFactory.forKind(JavaKind.fromJavaClass(target.getDescriptor().getResultType())); if (prependThread) { ValueNode[] targetArguments = new ValueNode[1 + params.length]; targetArguments[0] = thread; System.arraycopy(params, 0, targetArguments, 1, params.length); - return kit.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), targetArguments)); + return kit.append(new StubForeignCallNode(providers.getForeignCalls(), stamp, target.getDescriptor(), targetArguments)); } else { - return kit.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), params)); + return kit.append(new StubForeignCallNode(providers.getForeignCalls(), stamp, target.getDescriptor(), params)); } } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java Thu Apr 06 23:01:27 2017 +0000 @@ -25,6 +25,7 @@ import static org.graalvm.compiler.core.GraalCompiler.emitBackEnd; import static org.graalvm.compiler.core.GraalCompiler.emitFrontEnd; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugStubsAndSnippets; import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER; import static org.graalvm.util.CollectionsUtil.allMatch; @@ -35,6 +36,7 @@ import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugConfig; import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; @@ -176,7 +178,8 @@ @SuppressWarnings("try") public synchronized InstalledCode getCode(final Backend backend) { if (code == null) { - try (Scope d = Debug.sandbox("CompilingStub", DebugScope.getConfig(), providers.getCodeCache(), debugScopeContext())) { + DebugConfig config = DebugStubsAndSnippets.getValue(options) ? DebugScope.getConfig() : Debug.silentConfig(); + try (Scope d = Debug.sandbox("CompilingStub", config, providers.getCodeCache(), debugScopeContext())) { CodeCacheProvider codeCache = providers.getCodeCache(); CompilationResult compResult = buildCompilationResult(backend); @@ -184,7 +187,7 @@ assert destroyedCallerRegisters != null; // Add a GeneratePIC check here later, we don't want to install // code if we don't have a corresponding VM global symbol. - HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(null, null, compResult); + HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult); code = codeCache.installCode(null, compiledCode, null, null, false); } catch (Throwable e) { throw Debug.handle(e);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java Thu Apr 06 23:01:27 2017 +0000 @@ -122,6 +122,6 @@ public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_RETURN_ADDRESS = newDescriptor(UnwindExceptionToCallerStub.class, "exceptionHandlerForReturnAddress", Word.class, Word.class, Word.class); - @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = StubForeignCallNode.class) public static native Word exceptionHandlerForReturnAddress(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForReturnAddress, Word thread, Word returnAddress); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java Thu Apr 06 23:01:27 2017 +0000 @@ -1051,8 +1051,8 @@ public static BciBlockMapping create(BytecodeStream stream, Bytecode code, OptionValues options) { BciBlockMapping map = new BciBlockMapping(code); map.build(stream, options); - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { - Debug.dump(Debug.INFO_LOG_LEVEL, map, code.getMethod().format("After block building %f %R %H.%n(%P)")); + if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) { + Debug.dump(Debug.INFO_LEVEL, map, code.getMethod().format("After block building %f %R %H.%n(%P)")); } return map;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Thu Apr 06 23:01:27 2017 +0000 @@ -247,7 +247,6 @@ import static org.graalvm.compiler.core.common.type.StampFactory.objectNonNull; import static org.graalvm.compiler.debug.GraalError.guarantee; import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere; -import static org.graalvm.compiler.java.BytecodeParserOptions.DumpDuringGraphBuilding; import static org.graalvm.compiler.java.BytecodeParserOptions.TraceBytecodeParserLevel; import static org.graalvm.compiler.java.BytecodeParserOptions.TraceInlineDuringParsing; import static org.graalvm.compiler.java.BytecodeParserOptions.TraceParserPlugins; @@ -272,8 +271,8 @@ import org.graalvm.compiler.bytecode.Bytes; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider; +import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.PermanentBailoutException; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.calc.FloatConvert; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; @@ -770,10 +769,6 @@ for (BciBlock block : blocks) { processBlock(block); } - - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL) && DumpDuringGraphBuilding.getValue(options) && this.beforeReturnNode != startInstruction) { - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Bytecodes parsed: %s.%s", method.getDeclaringClass().getUnqualifiedName(), method.getName()); - } } } @@ -890,7 +885,7 @@ */ protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) { assert !graphBuilderConfig.eagerResolving(); - append(new FixedGuardNode(graph.unique(IsNullNode.create(object)), Unresolved, InvalidateRecompile)); + append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(object)), Unresolved, InvalidateRecompile)); frameState.push(JavaKind.Object, appendConstant(JavaConstant.NULL_POINTER)); } @@ -902,7 +897,7 @@ assert !graphBuilderConfig.eagerResolving(); AbstractBeginNode successor = graph.add(new BeginNode()); DeoptimizeNode deopt = graph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - append(new IfNode(graph.unique(IsNullNode.create(object)), successor, deopt, 1)); + append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(object)), successor, deopt, 1)); lastInstr = successor; frameState.push(JavaKind.Int, appendConstant(JavaConstant.INT_0)); } @@ -1060,15 +1055,15 @@ } protected ValueNode genNegateOp(ValueNode x) { - return (new NegateNode(x)); + return NegateNode.create(x); } protected ValueNode genLeftShift(ValueNode x, ValueNode y) { - return new LeftShiftNode(x, y); + return LeftShiftNode.create(x, y); } protected ValueNode genRightShift(ValueNode x, ValueNode y) { - return new RightShiftNode(x, y); + return RightShiftNode.create(x, y); } protected ValueNode genUnsignedRightShift(ValueNode x, ValueNode y) { @@ -1123,11 +1118,11 @@ } protected LogicNode genIntegerEquals(ValueNode x, ValueNode y) { - return IntegerEqualsNode.create(x, y, constantReflection); + return IntegerEqualsNode.create(x, y); } protected LogicNode genIntegerLessThan(ValueNode x, ValueNode y) { - return IntegerLessThanNode.create(x, y, constantReflection); + return IntegerLessThanNode.create(x, y); } protected ValueNode genUnique(ValueNode x) { @@ -1146,8 +1141,8 @@ genInfoPointNode(InfopointReason.BYTECODE_POSITION, null); ValueNode exception = frameState.pop(JavaKind.Object); - FixedGuardNode nullCheck = append(new FixedGuardNode(graph.unique(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true)); - PiNode nonNullException = graph.unique(new PiNode(exception, exception.stamp().join(objectNonNull()), nullCheck)); + FixedGuardNode nullCheck = append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true)); + ValueNode nonNullException = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp().join(objectNonNull()), nullCheck)); lastInstr.setNext(handleException(nonNullException, bci())); } @@ -1172,7 +1167,7 @@ } protected ValueNode genConditional(ValueNode x) { - return new ConditionalNode((LogicNode) x); + return ConditionalNode.create((LogicNode) x); } protected NewInstanceNode createNewInstance(ResolvedJavaType type, boolean fillContents) { @@ -1190,9 +1185,11 @@ protected ValueNode genLoadField(ValueNode receiver, ResolvedJavaField field) { StampPair stamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, field.getType(), false); if (stamp == null) { - return LoadFieldNode.create(this.graph.getAssumptions(), receiver, field); + return LoadFieldNode.create(getConstantFieldProvider(), getConstantReflection(), getMetaAccess(), getOptions(), + getAssumptions(), receiver, field, false, false); } else { - return LoadFieldNode.createOverrideStamp(stamp, receiver, field); + return LoadFieldNode.createOverrideStamp(getConstantFieldProvider(), getConstantReflection(), getMetaAccess(), getOptions(), + stamp, receiver, field, false, false); } } @@ -1202,8 +1199,8 @@ } BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class)); AbstractBeginNode falseSucc = graph.add(new BeginNode()); - PiNode nonNullReceiver = graph.unique(new PiNode(receiver, objectNonNull(), falseSucc)); - append(new IfNode(graph.unique(IsNullNode.create(receiver)), exception, falseSucc, 0.01)); + ValueNode nonNullReceiver = graph.addOrUnique(PiNode.create(receiver, objectNonNull(), falseSucc)); + append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(receiver)), exception, falseSucc, 0.01)); lastInstr = falseSucc; exception.setStateAfter(createFrameState(bci(), exception)); @@ -1215,7 +1212,7 @@ protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) { AbstractBeginNode trueSucc = graph.add(new BeginNode()); BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index)); - append(new IfNode(graph.unique(IntegerBelowNode.create(index, length, constantReflection)), trueSucc, exception, 0.99)); + append(new IfNode(genUnique(IntegerBelowNode.create(index, length)), trueSucc, exception, 0.99)); lastInstr = trueSucc; exception.setStateAfter(createFrameState(bci(), exception)); @@ -1401,11 +1398,6 @@ } if (invokeKind.hasReceiver()) { args[0] = emitExplicitExceptions(args[0]); - - if (args[0].isNullConstant()) { - append(new DeoptimizeNode(InvalidateRecompile, NullCheckException)); - return null; - } } InlineInfo inlineInfo = null; @@ -1419,6 +1411,11 @@ return null; } + if (invokeKind.hasReceiver() && args[0].isNullConstant()) { + append(new DeoptimizeNode(InvalidateRecompile, NullCheckException)); + return null; + } + if (!invokeKind.isIndirect() || (UseGuardedIntrinsics.getValue(options) && !GeneratePIC.getValue(options))) { if (tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType)) { if (TraceParserPlugins.getValue(options)) { @@ -1611,7 +1608,7 @@ LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver)); LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub)); ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess())); - LogicNode compare = graph.unique(CompareNode.createCompareNode(Condition.EQ, actual, expected, constantReflection)); + LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(Condition.EQ, actual, expected, constantReflection)); JavaTypeProfile profile = null; if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) { @@ -2125,8 +2122,8 @@ JsrScope scope = currentBlock.getJsrScope(); int retAddress = scope.nextReturnAddress(); ConstantNode returnBciNode = getJsrConstant(retAddress); - LogicNode guard = IntegerEqualsNode.create(local, returnBciNode, constantReflection); - guard = graph.unique(guard); + LogicNode guard = IntegerEqualsNode.create(local, returnBciNode); + guard = graph.addOrUniqueWithInputs(guard); append(new FixedGuardNode(guard, JavaSubroutineMismatch, InvalidateReprofile)); if (!successor.getJsrScope().equals(scope.pop())) { throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)"); @@ -2656,7 +2653,7 @@ } private DebugCloseable openNodeContext() { - if (graphBuilderConfig.trackNodeSourcePosition() && !parsingIntrinsic()) { + if ((graphBuilderConfig.trackNodeSourcePosition() || Debug.isDumpEnabledForMethod()) && !parsingIntrinsic()) { return graph.withNodeSourcePosition(createBytecodePosition()); } return null; @@ -2776,7 +2773,7 @@ genConstantTargetIf(trueBlock, falseBlock, negate, condition); } else { if (condition.graph() == null) { - condition = graph.unique(condition); + condition = genUnique(condition); } // Need to get probability based on current bci. @@ -3048,7 +3045,7 @@ int nextBCI = stream.nextBCI(); int nextBC = stream.readUByte(nextBCI); - if (nextBC == Bytecodes.GETFIELD) { + if (nextBCI <= currentBlock.endBci && nextBC == Bytecodes.GETFIELD) { stream.next(); genGetField(lookupField(stream.readCPI(), Bytecodes.GETFIELD), value); } else { @@ -3147,7 +3144,7 @@ default: throw shouldNotReachHere(); } - frameState.push(kind, append(v)); + frameState.push(kind, recursiveAppend(v)); } private void genIntegerDivOp(JavaKind kind, int opcode) { @@ -3194,7 +3191,7 @@ default: throw shouldNotReachHere(); } - frameState.push(kind, append(v)); + frameState.push(kind, recursiveAppend(v)); } private void genLogicOp(JavaKind kind, int opcode) { @@ -3217,7 +3214,7 @@ default: throw shouldNotReachHere(); } - frameState.push(kind, append(v)); + frameState.push(kind, recursiveAppend(v)); } private void genCompareOp(JavaKind kind, boolean isUnorderedLess) { @@ -3236,7 +3233,7 @@ if (from != from.getStackKind()) { input = append(genNarrow(input, from.getBitCount())); } - frameState.push(to, append(genSignExtend(input, to.getBitCount()))); + frameState.push(to, recursiveAppend(genSignExtend(input, to.getBitCount()))); } private void genZeroExtend(JavaKind from, JavaKind to) { @@ -3257,7 +3254,7 @@ int delta = getStream().readIncrement(); ValueNode x = frameState.loadLocal(index, JavaKind.Int); ValueNode y = appendConstant(JavaConstant.forInt(delta)); - frameState.storeLocal(index, JavaKind.Int, append(genIntegerAdd(x, y))); + frameState.storeLocal(index, JavaKind.Int, recursiveAppend(genIntegerAdd(x, y))); } private void genIfZero(Condition cond) { @@ -3373,7 +3370,7 @@ castNode = object; } else { FixedGuardNode fixedGuard = append(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile, false)); - castNode = append(new PiNode(object, StampFactory.objectNonNull(TypeReference.createExactTrusted(singleType)), fixedGuard)); + castNode = append(PiNode.create(object, StampFactory.objectNonNull(TypeReference.createExactTrusted(singleType)), fixedGuard)); } } } @@ -3386,7 +3383,7 @@ castNode = object; } else { FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false)); - castNode = append(new PiNode(object, StampFactory.object(checkedType, nonNull), fixedGuard)); + castNode = append(PiNode.create(object, StampFactory.object(checkedType, nonNull), fixedGuard)); } } frameState.push(JavaKind.Object, castNode); @@ -3431,7 +3428,7 @@ int next = getStream().nextBCI(); int value = getStream().readUByte(next); - if (value == Bytecodes.IFEQ || value == Bytecodes.IFNE) { + if (next <= currentBlock.endBci && (value == Bytecodes.IFEQ || value == Bytecodes.IFNE)) { getStream().next(); BciBlock firstSucc = currentBlock.getSuccessor(0); BciBlock secondSucc = currentBlock.getSuccessor(1); @@ -3678,11 +3675,10 @@ } private void genGetStatic(JavaField field) { - if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { - handleUnresolvedLoadField(field, null); + ResolvedJavaField resolvedField = resolveStaticFieldAccess(field, null); + if (resolvedField == null) { return; } - ResolvedJavaField resolvedField = (ResolvedJavaField) field; if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { graph.recordField(resolvedField); @@ -3712,13 +3708,39 @@ frameState.push(field.getJavaKind(), append(genLoadField(null, resolvedField))); } + private ResolvedJavaField resolveStaticFieldAccess(JavaField field, ValueNode value) { + if (field instanceof ResolvedJavaField) { + ResolvedJavaField resolvedField = (ResolvedJavaField) field; + if (resolvedField.getDeclaringClass().isInitialized()) { + return resolvedField; + } + /* + * Static fields have initialization semantics but may be safely accessed under certain + * conditions while the class is being initialized. Executing in the clinit or init of + * classes which are subtypes of the field holder are sure to be running in a context + * where the access is safe. + */ + if (resolvedField.getDeclaringClass().isAssignableFrom(method.getDeclaringClass())) { + if (method.isClassInitializer() || method.isConstructor()) { + return resolvedField; + } + } + } + if (value == null) { + handleUnresolvedLoadField(field, null); + } else { + handleUnresolvedStoreField(field, value, null); + + } + return null; + } + private void genPutStatic(JavaField field) { ValueNode value = frameState.pop(field.getJavaKind()); - if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { - handleUnresolvedStoreField(field, value, null); + ResolvedJavaField resolvedField = resolveStaticFieldAccess(field, value); + if (resolvedField == null) { return; } - ResolvedJavaField resolvedField = (ResolvedJavaField) field; if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { graph.recordField(resolvedField);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java Thu Apr 06 23:01:27 2017 +0000 @@ -52,9 +52,6 @@ @Option(help = "Maximum depth when inlining during bytecode parsing.", type = OptionType.Debug) public static final OptionKey<Integer> InlineDuringParsingMaxDepth = new OptionKey<>(10); - @Option(help = "Dump graphs after non-trivial changes during bytecode parsing.", type = OptionType.Debug) - public static final OptionKey<Boolean> DumpDuringGraphBuilding = new OptionKey<>(false); - @Option(help = "When creating info points hide the methods of the substitutions.", type = OptionType.Debug) public static final OptionKey<Boolean> HideSubstitutionStates = new OptionKey<>(false);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java Thu Apr 06 23:01:27 2017 +0000 @@ -22,6 +22,11 @@ */ package org.graalvm.compiler.lir.sparc; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.sparc.SPARC.CPU; +import static jdk.vm.ci.sparc.SPARC.g0; +import static jdk.vm.ci.sparc.SPARCKind.WORD; +import static jdk.vm.ci.sparc.SPARCKind.XWORD; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CBCOND; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.FBPCC; @@ -68,19 +73,14 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static org.graalvm.compiler.lir.sparc.SPARCMove.const2reg; import static org.graalvm.compiler.lir.sparc.SPARCOP3Op.emitOp3; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARC.CPU; -import static jdk.vm.ci.sparc.SPARC.g0; -import static jdk.vm.ci.sparc.SPARCKind.WORD; -import static jdk.vm.ci.sparc.SPARCKind.XWORD; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; + import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Assembler.LabelHint; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.sparc.SPARCAssembler; import org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict; import org.graalvm.compiler.asm.sparc.SPARCAssembler.CC; @@ -98,8 +98,8 @@ import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.util.EconomicMap; import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; @@ -159,6 +159,7 @@ public CompareBranchOp(AllocatableValue x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, SPARCKind kind, boolean unorderedIsTrue, double trueDestinationProbability) { super(TYPE, SIZE); + assert x.getPlatformKind() == y.getPlatformKind() : String.format("PlatformKind of x must match PlatformKind of y. %s!=%s", x.getPlatformKind(), y.getPlatformKind()); this.x = x; this.y = y; this.trueDestination = trueDestination; @@ -250,6 +251,7 @@ * @return true if the branch could be emitted */ private boolean emitShortCompareBranch(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + boolean isLong = kind == SPARCKind.XWORD; ConditionFlag actualConditionFlag = conditionFlag; Label actualTrueTarget = trueDestination.label(); Label actualFalseTarget = falseDestination.label(); @@ -274,7 +276,7 @@ actualFalseTarget = tmpTarget; } } - emitCBCond(masm, x, y, actualTrueTarget, actualConditionFlag); + emitCBCond(masm, x, y, actualTrueTarget, actualConditionFlag, isLong); if (needJump) { masm.jmp(actualFalseTarget); masm.nop(); @@ -282,16 +284,24 @@ return true; } - private void emitCBCond(SPARCMacroAssembler masm, Value actualX, Value actualY, Label actualTrueTarget, ConditionFlag cFlag) { + private static void emitCBCond(SPARCMacroAssembler masm, Value actualX, Value actualY, Label actualTrueTarget, ConditionFlag cFlag, boolean isLong) { PlatformKind xKind = actualX.getPlatformKind(); - boolean isLong = kind == SPARCKind.XWORD; + Register rs1 = asRegister(actualX, xKind); if (isJavaConstant(actualY)) { JavaConstant c = asJavaConstant(actualY); long constantY = c.isNull() ? 0 : c.asLong(); - assert NumUtil.isInt(constantY); - CBCOND.emit(masm, cFlag, isLong, asRegister(actualX, xKind), (int) constantY, actualTrueTarget); + try (ScratchRegister scratch = masm.getScratchRegister()) { + if (SPARCMacroAssembler.isSimm5(constantY)) { + CBCOND.emit(masm, cFlag, isLong, rs1, (int) constantY, actualTrueTarget); + } else { // !simm5 + Register rs2 = scratch.getRegister(); + masm.setx(constantY, rs2, false); + CBCOND.emit(masm, cFlag, isLong, rs1, rs2, actualTrueTarget); + } + } } else { - CBCOND.emit(masm, cFlag, isLong, asRegister(actualX, xKind), asRegister(actualY, xKind), actualTrueTarget); + Register rs2 = asRegister(actualY, xKind); + CBCOND.emit(masm, cFlag, isLong, rs1, rs2, actualTrueTarget); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java Thu Apr 06 23:01:27 2017 +0000 @@ -217,7 +217,7 @@ /** * Calculates the entry and exit states for all basic blocks. * - * @return Returns true on success and false if the the control flow is too complex. + * @return Returns true on success and false if the control flow is too complex. */ @SuppressWarnings("try") private boolean solveDataFlow(LIR lir) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/SwitchStrategy.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/SwitchStrategy.java Thu Apr 06 23:01:27 2017 +0000 @@ -46,7 +46,7 @@ private interface SwitchClosure { /** * Generates a conditional or unconditional jump. The jump will be unconditional if - * condition is null. If defaultTarget is true, then the jump will go the the default. + * condition is null. If defaultTarget is true, then the jump will go the default. * * @param index Index of the value and the jump target (only used if defaultTarget == false) * @param condition The condition on which to jump (can be null)
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java Thu Apr 06 23:01:27 2017 +0000 @@ -750,11 +750,11 @@ } } } - Debug.dump(Debug.BASIC_LOG_LEVEL, new LinearScanIntervalDumper(Arrays.copyOf(intervals, intervalsSize)), label); + Debug.dump(Debug.BASIC_LEVEL, new LinearScanIntervalDumper(Arrays.copyOf(intervals, intervalsSize)), label); } public void printLir(String label, @SuppressWarnings("unused") boolean hirValid) { - Debug.dump(Debug.INFO_LOG_LEVEL, ir, label); + Debug.dump(Debug.INFO_LEVEL, ir, label); } boolean verify() {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java Thu Apr 06 23:01:27 2017 +0000 @@ -110,12 +110,12 @@ interval.setSpillState(SpillState.StoreAtDefinition); return; } - Debug.log(Debug.VERBOSE_LOG_LEVEL, "Spill block candidate (initial): %s", spillBlock); + Debug.log(Debug.VERBOSE_LEVEL, "Spill block candidate (initial): %s", spillBlock); // move out of loops if (defBlock.getLoopDepth() < spillBlock.getLoopDepth()) { spillBlock = moveSpillOutOfLoop(defBlock, spillBlock); } - Debug.log(Debug.VERBOSE_LOG_LEVEL, "Spill block candidate (after loop optimizaton): %s", spillBlock); + Debug.log(Debug.VERBOSE_LEVEL, "Spill block candidate (after loop optimizaton): %s", spillBlock); /* * The spill block is the begin of the first split child (aka the value is on the @@ -134,7 +134,7 @@ spillBlock = dom; } if (defBlock.equals(spillBlock)) { - Debug.log(Debug.VERBOSE_LOG_LEVEL, "Definition is the best choice: %s", defBlock); + Debug.log(Debug.VERBOSE_LEVEL, "Definition is the best choice: %s", defBlock); // definition is the best choice interval.setSpillState(SpillState.StoreAtDefinition); return; @@ -146,7 +146,7 @@ } if (defBlock.probability() <= spillBlock.probability()) { - Debug.log(Debug.VERBOSE_LOG_LEVEL, "Definition has lower probability %s (%f) is lower than spill block %s (%f)", defBlock, defBlock.probability(), spillBlock, + Debug.log(Debug.VERBOSE_LEVEL, "Definition has lower probability %s (%f) is lower than spill block %s (%f)", defBlock, defBlock.probability(), spillBlock, spillBlock.probability()); // better spill block has the same probability -> do nothing interval.setSpillState(SpillState.StoreAtDefinition); @@ -164,7 +164,7 @@ AllocatableValue fromLocation = interval.getSplitChildAtOpId(spillOpId, OperandMode.DEF, allocator).location(); AllocatableValue toLocation = LinearScan.canonicalSpillOpr(interval); LIRInstruction move = allocator.getSpillMoveFactory().createMove(toLocation, fromLocation); - Debug.log(Debug.VERBOSE_LOG_LEVEL, "Insert spill move %s", move); + Debug.log(Debug.VERBOSE_LEVEL, "Insert spill move %s", move); move.setId(LinearScan.DOMINATOR_SPILL_MOVE_ID); /* * We can use the insertion buffer directly because we always insert at position 1.
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java Thu Apr 06 23:01:27 2017 +0000 @@ -861,7 +861,7 @@ * errors */ allocator.assignSpillSlot(interval); - Debug.dump(Debug.INFO_LOG_LEVEL, allocator.getLIR(), description); + Debug.dump(Debug.INFO_LEVEL, allocator.getLIR(), description); allocator.printIntervals(description); throw new OutOfRegistersException("LinearScan: no register found", description); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessAnalysisPhase.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessAnalysisPhase.java Thu Apr 06 23:01:27 2017 +0000 @@ -65,7 +65,7 @@ private final class Analyser { - private static final int LOG_LEVEL = Debug.INFO_LOG_LEVEL; + private static final int LOG_LEVEL = Debug.INFO_LEVEL; /** * Bit map specifying which operands are live upon entry to this block. These are values
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceBuilderPhase.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceBuilderPhase.java Thu Apr 06 23:01:27 2017 +0000 @@ -64,8 +64,8 @@ // @formatter:on } - private static final int TRACE_LOG_LEVEL = 1; - public static final int TRACE_DUMP_LEVEL = 3; + private static final int TRACE_LOG_LEVEL = Debug.BASIC_LEVEL; + public static final int TRACE_DUMP_LEVEL = Debug.VERBOSE_LEVEL; @Override protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceRegisterAllocationPhase.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceRegisterAllocationPhase.java Thu Apr 06 23:01:27 2017 +0000 @@ -89,7 +89,7 @@ final TraceRegisterAllocationPolicy plan = DefaultTraceRegisterAllocationPolicy.allocationPolicy(target, lirGenRes, spillMoveFactory, registerAllocationConfig, cachedStackSlots, resultTraces, neverSpillConstant, livenessInfo, lir.getOptions()); - Debug.dump(Debug.INFO_LOG_LEVEL, lir, "Before TraceRegisterAllocation"); + Debug.dump(Debug.INFO_LEVEL, lir, "Before TraceRegisterAllocation"); try (Scope s0 = Debug.scope("AllocateTraces", resultTraces, livenessInfo)) { for (Trace trace : resultTraces.getTraces()) { tracesCounter.increment(); @@ -101,9 +101,9 @@ } catch (Throwable e) { throw Debug.handle(e); } - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { + if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) { unnumberInstructions(lir); - Debug.dump(Debug.INFO_LOG_LEVEL, lir, "After trace allocation"); + Debug.dump(Debug.INFO_LEVEL, lir, "After trace allocation"); } TRACE_GLOBAL_MOVE_RESOLUTION_PHASE.apply(target, lirGenRes, traceContext);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanPhase.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanPhase.java Thu Apr 06 23:01:27 2017 +0000 @@ -1073,7 +1073,7 @@ } } } - Debug.dump(Debug.INFO_LOG_LEVEL, this, label); + Debug.dump(Debug.INFO_LEVEL, this, label); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanWalker.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanWalker.java Thu Apr 06 23:01:27 2017 +0000 @@ -954,7 +954,7 @@ * avoid errors */ allocator.assignSpillSlot(interval); - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { + if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) { dumpLIRAndIntervals(description); } throw new OutOfRegistersException("LinearScan: no register found", description); @@ -991,7 +991,7 @@ } protected void dumpLIRAndIntervals(String description) { - Debug.dump(Debug.INFO_LOG_LEVEL, allocator.getLIR(), description); + Debug.dump(Debug.INFO_LEVEL, allocator.getLIR(), description); allocator.printIntervals(description); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java Thu Apr 06 23:01:27 2017 +0000 @@ -461,7 +461,7 @@ if (block == null) { return; } - boolean emitComment = Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL) || PrintLIRWithAssembly.getValue(getOptions()); + boolean emitComment = Debug.isDumpEnabled(Debug.BASIC_LEVEL) || PrintLIRWithAssembly.getValue(getOptions()); if (emitComment) { blockComment(String.format("block B%d %s", block.getId(), block.getLoop())); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java Thu Apr 06 23:01:27 2017 +0000 @@ -214,7 +214,7 @@ phiConstantsSkipped.increment(); } phiConstants.set(var.index); - Debug.log(Debug.VERBOSE_LOG_LEVEL, "Removing phi variable: %s", var); + Debug.log(Debug.VERBOSE_LEVEL, "Removing phi variable: %s", var); } } else { assert defined.get(var.index) : "phi but not defined? " + var; @@ -291,7 +291,7 @@ // no better solution found materializeAtDefinitionSkipped.increment(); } - Debug.dump(Debug.INFO_LOG_LEVEL, constTree, "ConstantTree for %s", tree.getVariable()); + Debug.dump(Debug.DETAILED_LEVEL, constTree, "ConstantTree for %s", tree.getVariable()); } private void createLoads(DefUseTree tree, ConstantTree constTree, AbstractBlockBase<?> startBlock) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTreeAnalyzer.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTreeAnalyzer.java Thu Apr 06 23:01:27 2017 +0000 @@ -72,19 +72,19 @@ worklist.offerLast(startBlock); while (!worklist.isEmpty()) { AbstractBlockBase<?> block = worklist.pollLast(); - try (Indent i = Debug.logAndIndent(Debug.VERBOSE_LOG_LEVEL, "analyze: %s", block)) { + try (Indent i = Debug.logAndIndent(Debug.VERBOSE_LEVEL, "analyze: %s", block)) { assert block != null : "worklist is empty!"; assert isMarked(block) : "Block not part of the dominator tree: " + block; if (isLeafBlock(block)) { - Debug.log(Debug.VERBOSE_LOG_LEVEL, "leaf block"); + Debug.log(Debug.VERBOSE_LEVEL, "leaf block"); leafCost(block); continue; } if (!visited.get(block.getId())) { // if not yet visited (and not a leaf block) process all children first! - Debug.log(Debug.VERBOSE_LOG_LEVEL, "not marked"); + Debug.log(Debug.VERBOSE_LEVEL, "not marked"); worklist.offerLast(block); AbstractBlockBase<?> dominated = block.getFirstDominated(); while (dominated != null) { @@ -93,7 +93,7 @@ } visited.set(block.getId()); } else { - Debug.log(Debug.VERBOSE_LOG_LEVEL, "marked"); + Debug.log(Debug.VERBOSE_LEVEL, "marked"); // otherwise, process block process(block); } @@ -162,7 +162,7 @@ private void filteredPush(Deque<AbstractBlockBase<?>> worklist, AbstractBlockBase<?> block) { if (isMarked(block)) { - Debug.log(Debug.VERBOSE_LOG_LEVEL, "adding %s to the worklist", block); + Debug.log(Debug.VERBOSE_LEVEL, "adding %s to the worklist", block); worklist.offerLast(block); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/LIRPhase.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/LIRPhase.java Thu Apr 06 23:01:27 2017 +0000 @@ -113,8 +113,8 @@ try (Scope s = Debug.scope(getName(), this)) { try (DebugCloseable a = timer.start(); DebugCloseable c = memUseTracker.start()) { run(target, lirGenRes, context); - if (dumpLIR && Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, lirGenRes.getLIR(), "%s", getName()); + if (dumpLIR && Debug.isDumpEnabled(Debug.BASIC_LEVEL)) { + Debug.dump(Debug.BASIC_LEVEL, lirGenRes.getLIR(), "%s", getName()); } } } catch (Throwable e) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAVerifier.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAVerifier.java Thu Apr 06 23:01:27 2017 +0000 @@ -87,7 +87,7 @@ doBlock(pred); } } - try (Indent indent = Debug.logAndIndent(Debug.INFO_LOG_LEVEL, "handle block %s", b)) { + try (Indent indent = Debug.logAndIndent(Debug.INFO_LEVEL, "handle block %s", b)) { assert verifyBlock(b); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java Thu Apr 06 23:01:27 2017 +0000 @@ -131,7 +131,7 @@ @SuppressWarnings("try") private void allocate() { - Debug.dump(Debug.INFO_LOG_LEVEL, lir, "After StackSlot numbering"); + Debug.dump(Debug.INFO_LEVEL, lir, "After StackSlot numbering"); long currentFrameSize = StackSlotAllocatorUtil.allocatedFramesize.isEnabled() ? frameMapBuilder.getFrameMap().currentFrameSize() : 0; EconomicSet<LIRInstruction> usePos; @@ -145,14 +145,14 @@ assert verifyIntervals(); } } - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { + if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) { dumpIntervals("Before stack slot allocation"); } // step 4: allocate stack slots try (DebugCloseable t = AllocateSlotsTimer.start()) { allocateStackSlots(); } - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { + if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) { dumpIntervals("After stack slot allocation"); } @@ -160,7 +160,7 @@ try (DebugCloseable t = AssignSlotsTimer.start()) { assignStackSlots(usePos); } - Debug.dump(Debug.INFO_LOG_LEVEL, lir, "After StackSlot assignment"); + Debug.dump(Debug.INFO_LEVEL, lir, "After StackSlot assignment"); if (StackSlotAllocatorUtil.allocatedFramesize.isEnabled()) { StackSlotAllocatorUtil.allocatedFramesize.add(frameMapBuilder.getFrameMap().currentFrameSize() - currentFrameSize); } @@ -256,13 +256,13 @@ */ location = StackSlot.get(current.kind(), slot.getRawOffset(), slot.getRawAddFrameSize()); StackSlotAllocatorUtil.reusedSlots.increment(); - Debug.log(Debug.BASIC_LOG_LEVEL, "Reuse stack slot %s (reallocated from %s) for virtual stack slot %s", location, slot, virtualSlot); + Debug.log(Debug.BASIC_LEVEL, "Reuse stack slot %s (reallocated from %s) for virtual stack slot %s", location, slot, virtualSlot); } else { // Allocate new stack slot. location = frameMapBuilder.getFrameMap().allocateSpillSlot(virtualSlot.getValueKind()); StackSlotAllocatorUtil.virtualFramesize.add(frameMapBuilder.getFrameMap().spillSlotSize(virtualSlot.getValueKind())); StackSlotAllocatorUtil.allocatedSlots.increment(); - Debug.log(Debug.BASIC_LOG_LEVEL, "New stack slot %s for virtual stack slot %s", location, virtualSlot); + Debug.log(Debug.BASIC_LEVEL, "New stack slot %s for virtual stack slot %s", location, virtualSlot); } } Debug.log("Allocate location %s for interval %s", location, current); @@ -434,7 +434,7 @@ } private void dumpIntervals(String label) { - Debug.dump(Debug.INFO_LOG_LEVEL, new StackIntervalDumper(Arrays.copyOf(stackSlotMap, stackSlotMap.length)), label); + Debug.dump(Debug.INFO_LEVEL, new StackIntervalDumper(Arrays.copyOf(stackSlotMap, stackSlotMap.length)), label); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopFullUnrollPhase.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopFullUnrollPhase.java Thu Apr 06 23:01:27 2017 +0000 @@ -54,7 +54,7 @@ Debug.log("FullUnroll %s", loop); LoopTransformations.fullUnroll(loop, context, canonicalizer); FULLY_UNROLLED_LOOPS.increment(); - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "FullUnroll %s", loop); + Debug.dump(Debug.DETAILED_LEVEL, graph, "FullUnroll %s", loop); peeled = true; break; }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPeelingPhase.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPeelingPhase.java Thu Apr 06 23:01:27 2017 +0000 @@ -45,7 +45,7 @@ if (getPolicies().shouldPeel(loop, data.getCFG(), context.getMetaAccess())) { Debug.log("Peeling %s", loop); LoopTransformations.peel(loop); - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Peeling %s", loop); + Debug.dump(Debug.DETAILED_LEVEL, graph, "Peeling %s", loop); } } data.deleteUnusedNodes();
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopUnswitchingPhase.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopUnswitchingPhase.java Thu Apr 06 23:01:27 2017 +0000 @@ -61,7 +61,7 @@ logUnswitch(loop, controlSplits); } LoopTransformations.unswitch(loop, controlSplits); - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "After unswitch %s", controlSplits); + Debug.dump(Debug.DETAILED_LEVEL, graph, "After unswitch %s", controlSplits); UNSWITCHED.increment(); unswitched = true; break;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopsDataTest.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopsDataTest.java Thu Apr 06 23:01:27 2017 +0000 @@ -77,8 +77,8 @@ Assert.assertEquals(1, loops.outerFirst().get(0).loop().getDepth()); Assert.assertEquals(1, loops.outerFirst().get(1).loop().getDepth()); Assert.assertEquals(2, loops.outerFirst().get(2).loop().getDepth()); - Assert.assertEquals(2, loops.outerFirst().get(3).loop().getDepth()); - Assert.assertEquals(3, loops.outerFirst().get(4).loop().getDepth()); + Assert.assertEquals(3, loops.outerFirst().get(3).loop().getDepth()); + Assert.assertEquals(2, loops.outerFirst().get(4).loop().getDepth()); Assert.assertEquals(2, loops.outerFirst().get(5).loop().getDepth()); Assert.assertEquals(3, loops.outerFirst().get(6).loop().getDepth()); Assert.assertEquals(4, loops.outerFirst().get(7).loop().getDepth());
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedOffsetInductionVariable.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedOffsetInductionVariable.java Thu Apr 06 23:01:27 2017 +0000 @@ -90,7 +90,7 @@ @Override public ValueNode strideNode() { if (value instanceof SubNode && base.valueNode() == value.getY()) { - return graph().unique(new NegateNode(base.strideNode())); + return graph().addOrUniqueWithInputs(NegateNode.create(base.strideNode())); } return base.strideNode(); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ArrayListBenchmark.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ArrayListBenchmark.java Thu Apr 06 23:01:27 2017 +0000 @@ -24,13 +24,14 @@ import java.util.ArrayList; +import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark; import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Level; import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; -import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark; - /** * Benchmarks cost of ArrayList. */ @@ -40,7 +41,7 @@ @State(Scope.Benchmark) public static class ThreadState { - ArrayList<Integer> list = new ArrayList<>(N); + final ArrayList<Integer> list = new ArrayList<>(N); } @Benchmark @@ -61,9 +62,20 @@ state.list.clear(); } + @State(Scope.Benchmark) + public static class ClearedThreadState { + final ArrayList<Integer> list = new ArrayList<>(N); + + // We don't want to measure the cost of list clearing + @Setup(Level.Invocation) + public void beforeInvocation() { + list.clear(); + } + } + @Benchmark @Warmup(iterations = 20) - public void addNull(ThreadState state) { + public void addNull(ClearedThreadState state) { for (int i = 0; i < N; ++i) { state.list.add(null); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java Thu Apr 06 23:01:27 2017 +0000 @@ -374,13 +374,17 @@ codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock); linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock); - LIR lir = new LIR(cfg, linearScanOrder, codeEmittingOrder, graph.getOptions()); + LIR lir = new LIR(cfg, linearScanOrder, codeEmittingOrder, getGraphOptions()); FrameMapBuilder frameMapBuilder = request.backend.newFrameMapBuilder(registerConfig); lirGenRes = request.backend.newLIRGenerationResult(graph.compilationId(), lir, frameMapBuilder, request.graph, stub); lirGenTool = request.backend.newLIRGenerator(lirGenRes); nodeLirGen = request.backend.newNodeLIRBuilder(request.graph, lirGenTool); } + protected OptionValues getGraphOptions() { + return graph.getOptions(); + } + private static ControlFlowGraph deepCopy(ControlFlowGraph cfg) { return ControlFlowGraph.compute(cfg.graph, true, true, true, true); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/trace/TraceLSRAIntervalBuildingBench.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/trace/TraceLSRAIntervalBuildingBench.java Thu Apr 06 23:01:27 2017 +0000 @@ -28,6 +28,7 @@ import org.graalvm.compiler.lir.alloc.trace.GlobalLivenessAnalysisPhase; import org.graalvm.compiler.lir.alloc.trace.GlobalLivenessInfo; import org.graalvm.compiler.lir.alloc.trace.TraceBuilderPhase; +import org.graalvm.compiler.lir.alloc.trace.TraceRegisterAllocationPhase; import org.graalvm.compiler.lir.alloc.trace.lsra.TraceLinearScanLifetimeAnalysisPhase; import org.graalvm.compiler.lir.alloc.trace.lsra.TraceLinearScanLifetimeAnalysisPhase.Analyser; import org.graalvm.compiler.lir.alloc.trace.lsra.TraceLinearScanPhase; @@ -40,6 +41,7 @@ import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark; import org.graalvm.compiler.microbenchmarks.lir.GraalCompilerState; +import org.graalvm.compiler.options.OptionValues; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.Level; import org.openjdk.jmh.annotations.Param; @@ -90,6 +92,11 @@ return new LIRSuites(ls.getPreAllocationOptimizationStage(), allocationStage, ls.getPostAllocationOptimizationStage()); } + @Override + protected OptionValues getGraphOptions() { + return new OptionValues(super.getGraphOptions(), TraceRegisterAllocationPhase.Options.TraceRAuseInterTraceHints, false); + } + @Setup(Level.Trial) public void setup() { initializeMethod();
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -86,8 +86,8 @@ /* * Don't allow guards with action None and reason RuntimeConstraint to float. In cases * where 2 guards are testing equivalent conditions they might be lowered at the same - * location. If the guard with the None action is lowered before the the other guard - * then the code will be stuck repeatedly deoptimizing without invalidating the code. + * location. If the guard with the None action is lowered before the other guard then + * the code will be stuck repeatedly deoptimizing without invalidating the code. * Conditional elimination will eliminate the guard if it's truly redundant in this * case. */
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java Thu Apr 06 23:01:27 2017 +0000 @@ -105,7 +105,7 @@ */ @OptionalInput NodeInputList<ValueNode> values; - @OptionalInput(Association) NodeInputList<MonitorIdNode> monitorIds; + @Input(Association) NodeInputList<MonitorIdNode> monitorIds; @OptionalInput(State) NodeInputList<EscapeObjectState> virtualObjectMappings;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java Thu Apr 06 23:01:27 2017 +0000 @@ -37,8 +37,8 @@ import java.util.SortedMap; import java.util.TreeMap; +import org.graalvm.compiler.core.common.Fields; import org.graalvm.compiler.core.common.PermanentBailoutException; -import org.graalvm.compiler.core.common.Fields; import org.graalvm.compiler.core.common.util.TypeReader; import org.graalvm.compiler.core.common.util.UnsafeArrayTypeReader; import org.graalvm.compiler.debug.Debug; @@ -61,9 +61,9 @@ import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin.LoopExplosionKind; -import org.graalvm.util.Equivalence; import org.graalvm.util.EconomicMap; import org.graalvm.util.EconomicSet; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.meta.DeoptimizationAction; @@ -85,8 +85,6 @@ protected class MethodScope { /** The loop that contains the call. Only non-null during method inlining. */ public final LoopScope callerLoopScope; - /** The target graph where decoded nodes are added to. */ - public final StructuredGraph graph; /** * Mark for nodes that were present before the decoding of this method started. Note that * nodes that were decoded after the mark can still be part of an outer method, since @@ -95,20 +93,19 @@ public final Graph.Mark methodStartMark; /** The encode graph that is decoded. */ public final EncodedGraph encodedGraph; + /** The highest node order id that a fixed node has in the EncodedGraph. */ + public final int maxFixedNodeOrderId; /** Access to the encoded graph. */ public final TypeReader reader; /** The kind of loop explosion to be performed during decoding. */ public final LoopExplosionKind loopExplosion; - /** A list of tasks to run before the method scope is closed. */ - public final List<Runnable> cleanupTasks; /** All return nodes encountered during decoding. */ - public final List<ReturnNode> returnNodes; - /** The exception unwind node encountered during decoding, or null. */ - public final List<UnwindNode> unwindNodes; + public final List<ControlSinkNode> returnAndUnwindNodes; /** All merges created during loop explosion. */ public final EconomicSet<Node> loopExplosionMerges; + /** * The start of explosion, and the merge point for when irreducible loops are detected. Only * used when {@link MethodScope#loopExplosion} is {@link LoopExplosionKind#MERGE_EXPLODE}. @@ -117,16 +114,14 @@ protected MethodScope(LoopScope callerLoopScope, StructuredGraph graph, EncodedGraph encodedGraph, LoopExplosionKind loopExplosion) { this.callerLoopScope = callerLoopScope; - this.graph = graph; this.methodStartMark = graph.getMark(); this.encodedGraph = encodedGraph; this.loopExplosion = loopExplosion; - this.cleanupTasks = new ArrayList<>(2); - this.returnNodes = new ArrayList<>(1); - this.unwindNodes = new ArrayList<>(0); + this.returnAndUnwindNodes = new ArrayList<>(2); if (encodedGraph != null) { reader = UnsafeArrayTypeReader.create(encodedGraph.getEncoding(), encodedGraph.getStartOffset(), architecture.supportsUnalignedMemoryAccess()); + maxFixedNodeOrderId = reader.getUVInt(); if (encodedGraph.nodeStartOffsets == null) { int nodeCount = reader.getUVInt(); int[] nodeStartOffsets = new int[nodeCount]; @@ -137,6 +132,7 @@ } } else { reader = null; + maxFixedNodeOrderId = 0; } if (loopExplosion != LoopExplosionKind.NONE) { @@ -145,6 +141,10 @@ loopExplosionMerges = null; } } + + public boolean isInlinedMethod() { + return false; + } } /** Decoding state maintained for each loop in the encoded graph. */ @@ -175,23 +175,24 @@ public final Node[] createdNodes; /** * Nodes that have been created in outer loop scopes and existed before starting to process - * this loop, indexed by the orderId. + * this loop, indexed by the orderId. Only used when {@link MethodScope#loopExplosion} is + * not {@link LoopExplosionKind#NONE}. */ public final Node[] initialCreatedNodes; protected LoopScope(MethodScope methodScope) { this.methodScope = methodScope; this.outer = null; - this.nextIterations = methodScope.loopExplosion == LoopExplosionKind.FULL_EXPLODE_UNTIL_RETURN ? new ArrayDeque<>() : null; + this.nextIterations = methodScope.loopExplosion == LoopExplosionKind.FULL_EXPLODE_UNTIL_RETURN ? new ArrayDeque<>(2) : null; this.loopDepth = 0; this.loopIteration = 0; this.iterationStates = null; this.loopBeginOrderId = -1; int nodeCount = methodScope.encodedGraph.nodeStartOffsets.length; - this.nodesToProcess = new BitSet(nodeCount); - this.initialCreatedNodes = new Node[nodeCount]; + this.nodesToProcess = new BitSet(methodScope.maxFixedNodeOrderId); this.createdNodes = new Node[nodeCount]; + this.initialCreatedNodes = null; } protected LoopScope(MethodScope methodScope, LoopScope outer, int loopDepth, int loopIteration, int loopBeginOrderId, Node[] initialCreatedNodes, Node[] createdNodes, @@ -203,9 +204,9 @@ this.nextIterations = nextIterations; this.iterationStates = iterationStates; this.loopBeginOrderId = loopBeginOrderId; - this.nodesToProcess = new BitSet(initialCreatedNodes.length); + this.nodesToProcess = new BitSet(methodScope.maxFixedNodeOrderId); this.initialCreatedNodes = initialCreatedNodes; - this.createdNodes = Arrays.copyOf(createdNodes, createdNodes.length); + this.createdNodes = createdNodes; } @Override @@ -338,18 +339,23 @@ } protected final Architecture architecture; + /** The target graph where decoded nodes are added to. */ + protected final StructuredGraph graph; + private final EconomicMap<NodeClass<?>, ArrayDeque<Node>> reusableFloatingNodes; - public GraphDecoder(Architecture architecture) { + public GraphDecoder(Architecture architecture, StructuredGraph graph) { this.architecture = architecture; + this.graph = graph; + reusableFloatingNodes = EconomicMap.create(Equivalence.IDENTITY); } @SuppressWarnings("try") - public final void decode(StructuredGraph graph, EncodedGraph encodedGraph) { + public final void decode(EncodedGraph encodedGraph) { try (Debug.Scope scope = Debug.scope("GraphDecoder", graph)) { MethodScope methodScope = new MethodScope(null, graph, encodedGraph, LoopExplosionKind.NONE); decode(createInitialLoopScope(methodScope, null)); cleanupGraph(methodScope); - assert methodScope.graph.verify(); + assert graph.verify(); } catch (Throwable ex) { Debug.handle(ex); } @@ -370,14 +376,10 @@ startNode.setNext(firstNode); loopScope.nodesToProcess.set(GraphEncoder.FIRST_NODE_ORDER_ID); } else { - firstNode = methodScope.graph.start(); + firstNode = graph.start(); registerNode(loopScope, GraphEncoder.START_NODE_ORDER_ID, firstNode, false, false); loopScope.nodesToProcess.set(GraphEncoder.START_NODE_ORDER_ID); } - - if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) { - methodScope.cleanupTasks.add(new LoopDetector(methodScope, startNode)); - } return loopScope; } @@ -411,18 +413,26 @@ } /* - * Finished with an inlined method. Perform all registered end-of-method cleanup tasks - * and continue with loop that contained the call. + * Finished with an inlined method. Perform end-of-method cleanup tasks. */ - for (Runnable task : methodScope.cleanupTasks) { - task.run(); + if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) { + LoopDetector loopDetector = new LoopDetector(graph, methodScope); + loopDetector.run(); } + if (methodScope.isInlinedMethod()) { + finishInlining(methodScope); + } + + /* continue with the caller */ loopScope = methodScope.callerLoopScope; } } + protected void finishInlining(@SuppressWarnings("unused") MethodScope inlineScope) { + } + private static void propagateCreatedNodes(LoopScope loopScope) { - if (loopScope.outer == null) { + if (loopScope.outer == null || loopScope.createdNodes != loopScope.outer.createdNodes) { return; } @@ -474,7 +484,7 @@ LoopScope outerScope = loopScope.outer; int nextIterationNumber = outerScope.nextIterations.isEmpty() ? outerScope.loopIteration + 1 : outerScope.nextIterations.getLast().loopIteration + 1; successorAddScope = new LoopScope(methodScope, outerScope.outer, outerScope.loopDepth, nextIterationNumber, outerScope.loopBeginOrderId, outerScope.initialCreatedNodes, - loopScope.initialCreatedNodes, outerScope.nextIterations, outerScope.iterationStates); + Arrays.copyOf(loopScope.initialCreatedNodes, loopScope.initialCreatedNodes.length), outerScope.nextIterations, outerScope.iterationStates); checkLoopExplosionIteration(methodScope, successorAddScope); /* @@ -496,8 +506,8 @@ methodScope.reader.setByteIndex(methodScope.encodedGraph.nodeStartOffsets[nodeOrderId]); int typeId = methodScope.reader.getUVInt(); assert node.getNodeClass() == methodScope.encodedGraph.getNodeClasses()[typeId]; + makeFixedNodeInputs(methodScope, loopScope, node); readProperties(methodScope, node); - makeInputNodes(methodScope, loopScope, node, true); makeSuccessorStubs(methodScope, successorAddScope, node, updatePredecessors); LoopScope resultScope = loopScope; @@ -533,13 +543,16 @@ if (merge instanceof LoopBeginNode) { assert phiNodeScope == phiInputScope && phiNodeScope == loopScope; resultScope = new LoopScope(methodScope, loopScope, loopScope.loopDepth + 1, 0, mergeOrderId, - Arrays.copyOf(loopScope.createdNodes, loopScope.createdNodes.length), loopScope.createdNodes, // - methodScope.loopExplosion != LoopExplosionKind.NONE ? new ArrayDeque<>() : null, // + methodScope.loopExplosion != LoopExplosionKind.NONE ? Arrays.copyOf(loopScope.createdNodes, loopScope.createdNodes.length) : null, + methodScope.loopExplosion != LoopExplosionKind.NONE ? Arrays.copyOf(loopScope.createdNodes, loopScope.createdNodes.length) : loopScope.createdNodes, // + methodScope.loopExplosion != LoopExplosionKind.NONE ? new ArrayDeque<>(2) : null, // methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE ? EconomicMap.create(Equivalence.DEFAULT) : null); phiInputScope = resultScope; phiNodeScope = resultScope; - registerNode(loopScope, mergeOrderId, null, true, true); + if (methodScope.loopExplosion != LoopExplosionKind.NONE) { + registerNode(loopScope, mergeOrderId, null, true, true); + } loopScope.nodesToProcess.clear(mergeOrderId); resultScope.nodesToProcess.set(mergeOrderId); } @@ -551,11 +564,8 @@ InvokeData invokeData = readInvokeData(methodScope, nodeOrderId, (Invoke) node); resultScope = handleInvoke(methodScope, loopScope, invokeData); - } else if (node instanceof ReturnNode) { - methodScope.returnNodes.add((ReturnNode) node); - } else if (node instanceof UnwindNode) { - methodScope.unwindNodes.add((UnwindNode) node); - + } else if (node instanceof ReturnNode || node instanceof UnwindNode) { + methodScope.returnAndUnwindNodes.add((ControlSinkNode) node); } else { handleFixedNode(methodScope, loopScope, nodeOrderId, node); } @@ -642,7 +652,7 @@ } } - MergeNode merge = methodScope.graph.add(new MergeNode()); + MergeNode merge = graph.add(new MergeNode()); methodScope.loopExplosionMerges.add(merge); if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) { @@ -655,11 +665,11 @@ List<ValueNode> newFrameStateValues = new ArrayList<>(); for (ValueNode frameStateValue : frameState.values) { - if (frameStateValue == null || frameStateValue.isConstant() || !methodScope.graph.isNew(methodScope.methodStartMark, frameStateValue)) { + if (frameStateValue == null || frameStateValue.isConstant() || !graph.isNew(methodScope.methodStartMark, frameStateValue)) { newFrameStateValues.add(frameStateValue); } else { - ProxyPlaceholder newFrameStateValue = methodScope.graph.unique(new ProxyPlaceholder(frameStateValue, merge)); + ProxyPlaceholder newFrameStateValue = graph.unique(new ProxyPlaceholder(frameStateValue, merge)); newFrameStateValues.add(newFrameStateValue); /* @@ -670,14 +680,19 @@ if (loopScope.createdNodes[i] == frameStateValue) { loopScope.createdNodes[i] = newFrameStateValue; } - if (loopScope.initialCreatedNodes[i] == frameStateValue) { - loopScope.initialCreatedNodes[i] = newFrameStateValue; + } + + if (loopScope.initialCreatedNodes != null) { + for (int i = 0; i < loopScope.initialCreatedNodes.length; i++) { + if (loopScope.initialCreatedNodes[i] == frameStateValue) { + loopScope.initialCreatedNodes[i] = newFrameStateValue; + } } } } } - FrameState newFrameState = methodScope.graph.add(new FrameState(frameState.outerFrameState(), frameState.getCode(), frameState.bci, newFrameStateValues, frameState.localsSize(), + FrameState newFrameState = graph.add(new FrameState(frameState.outerFrameState(), frameState.getCode(), frameState.bci, newFrameStateValues, frameState.localsSize(), frameState.stackSize(), frameState.rethrowException(), frameState.duringCall(), frameState.monitorIds(), frameState.virtualObjectMappings())); frameState.replaceAtUsagesAndDelete(newFrameState); @@ -708,7 +723,7 @@ } protected FixedNode handleLoopExplosionEnd(MethodScope methodScope, LoopScope loopScope, LoopEndNode loopEnd) { - EndNode replacementNode = methodScope.graph.add(new EndNode()); + EndNode replacementNode = graph.add(new EndNode()); loopEnd.replaceAtPredecessor(replacementNode); loopEnd.safeDelete(); @@ -716,7 +731,7 @@ if (methodScope.loopExplosion != LoopExplosionKind.FULL_UNROLL || loopScope.nextIterations.isEmpty()) { int nextIterationNumber = loopScope.nextIterations.isEmpty() ? loopScope.loopIteration + 1 : loopScope.nextIterations.getLast().loopIteration + 1; LoopScope nextIterationScope = new LoopScope(methodScope, loopScope.outer, loopScope.loopDepth, nextIterationNumber, loopScope.loopBeginOrderId, loopScope.initialCreatedNodes, - loopScope.initialCreatedNodes, loopScope.nextIterations, loopScope.iterationStates); + Arrays.copyOf(loopScope.initialCreatedNodes, loopScope.initialCreatedNodes.length), loopScope.nextIterations, loopScope.iterationStates); checkLoopExplosionIteration(methodScope, nextIterationScope); loopScope.nextIterations.addLast(nextIterationScope); registerNode(nextIterationScope, loopScope.loopBeginOrderId, null, true, true); @@ -749,7 +764,9 @@ * The ProxyNode transports a value from the loop to the outer scope. We therefore * register it in the outer scope. */ - registerNode(loopScope.outer, proxyOrderId, proxy, false, false); + if (loopScope.outer.createdNodes != loopScope.createdNodes) { + registerNode(loopScope.outer, proxyOrderId, proxy, false, false); + } } } @@ -757,7 +774,7 @@ assert loopExit.stateAfter() == null; int stateAfterOrderId = readOrderId(methodScope); - BeginNode begin = methodScope.graph.add(new BeginNode()); + BeginNode begin = graph.add(new BeginNode()); FixedNode loopExitSuccessor = loopExit.next(); loopExit.replaceAtPredecessor(begin); @@ -768,14 +785,14 @@ * This exit might end up as a loop exit of a loop detected after partial evaluation. We * need to be able to create a FrameState and the necessary proxy nodes in this case. */ - loopExitPlaceholder = methodScope.graph.add(new MergeNode()); + loopExitPlaceholder = graph.add(new MergeNode()); methodScope.loopExplosionMerges.add(loopExitPlaceholder); - EndNode end = methodScope.graph.add(new EndNode()); + EndNode end = graph.add(new EndNode()); begin.setNext(end); loopExitPlaceholder.addForwardEnd(end); - begin = methodScope.graph.add(new BeginNode()); + begin = graph.add(new BeginNode()); loopExitPlaceholder.setNext(begin); } @@ -793,10 +810,10 @@ } else if (existingExit instanceof BeginNode) { /* Second loop iteration that exits. Create the merge. */ - merge = methodScope.graph.add(new MergeNode()); + merge = graph.add(new MergeNode()); registerNode(outerScope, loopExitOrderId, merge, true, false); /* Add the first iteration. */ - EndNode firstEnd = methodScope.graph.add(new EndNode()); + EndNode firstEnd = graph.add(new EndNode()); ((BeginNode) existingExit).setNext(firstEnd); merge.addForwardEnd(firstEnd); merge.setNext(loopExitSuccessor); @@ -807,7 +824,7 @@ } if (merge != null) { - EndNode end = methodScope.graph.add(new EndNode()); + EndNode end = graph.add(new EndNode()); begin.setNext(end); merge.addForwardEnd(end); } @@ -826,7 +843,7 @@ if (loopExitPlaceholder != null) { if (!phiInput.isConstant()) { - phiInput = methodScope.graph.unique(new ProxyPlaceholder(phiInput, loopExitPlaceholder)); + phiInput = graph.unique(new ProxyPlaceholder(phiInput, loopExitPlaceholder)); } registerNode(loopScope, proxyOrderId, phiInput, true, false); } @@ -843,7 +860,14 @@ } else if (!merge.isPhiAtMerge(existing)) { /* Now we have two different values, so we need to create a phi node. */ - PhiNode phi = methodScope.graph.addWithoutUnique(new ValuePhiNode(proxy.stamp(), merge)); + PhiNode phi; + if (proxy instanceof ValueProxyNode) { + phi = graph.addWithoutUnique(new ValuePhiNode(proxy.stamp(), merge)); + } else if (proxy instanceof GuardProxyNode) { + phi = graph.addWithoutUnique(new GuardPhiNode(merge)); + } else { + throw GraalError.shouldNotReachHere(); + } /* Add the inputs from all previous exits. */ for (int j = 0; j < merge.phiPredecessorCount() - 1; j++) { phi.addInput(existing); @@ -954,12 +978,6 @@ return false; } - protected Node instantiateNode(MethodScope methodScope, int nodeOrderId) { - methodScope.reader.setByteIndex(methodScope.encodedGraph.nodeStartOffsets[nodeOrderId]); - NodeClass<?> nodeClass = methodScope.encodedGraph.getNodeClasses()[methodScope.reader.getUVInt()]; - return nodeClass.allocateInstance(); - } - protected void readProperties(MethodScope methodScope, Node node) { node.setNodeSourcePosition((NodeSourcePosition) readObject(methodScope)); Fields fields = node.getNodeClass().getData(); @@ -980,7 +998,7 @@ * are created on demand (recursively since they can themselves reference not yet created * nodes). */ - protected void makeInputNodes(MethodScope methodScope, LoopScope loopScope, Node node, boolean updateUsages) { + protected void makeFixedNodeInputs(MethodScope methodScope, LoopScope loopScope, Node node) { Edges edges = node.getNodeClass().getInputEdges(); for (int index = 0; index < edges.getDirectCount(); index++) { if (skipDirectEdge(node, edges, index)) { @@ -989,25 +1007,60 @@ int orderId = readOrderId(methodScope); Node value = ensureNodeCreated(methodScope, loopScope, orderId); edges.initializeNode(node, index, value); - if (updateUsages && value != null && !value.isDeleted()) { + if (value != null && !value.isDeleted()) { edges.update(node, null, value); } } - for (int index = edges.getDirectCount(); index < edges.getCount(); index++) { - if (skipIndirectEdge(node, edges, index, true)) { - continue; + + if (node instanceof AbstractMergeNode) { + /* The ends of merge nodes are filled manually when the ends are processed. */ + assert edges.getCount() - edges.getDirectCount() == 1 : "MergeNode has one variable size input (the ends)"; + assert Edges.getNodeList(node, edges.getOffsets(), edges.getDirectCount()) != null : "Input list must have been already created"; + } else { + for (int index = edges.getDirectCount(); index < edges.getCount(); index++) { + int size = methodScope.reader.getSVInt(); + if (size != -1) { + NodeList<Node> nodeList = new NodeInputList<>(node, size); + edges.initializeList(node, index, nodeList); + for (int idx = 0; idx < size; idx++) { + int orderId = readOrderId(methodScope); + Node value = ensureNodeCreated(methodScope, loopScope, orderId); + nodeList.initialize(idx, value); + if (value != null && !value.isDeleted()) { + edges.update(node, null, value); + } + } + } } - int size = methodScope.reader.getSVInt(); - if (size != -1) { - NodeList<Node> nodeList = new NodeInputList<>(node, size); - edges.initializeList(node, index, nodeList); - for (int idx = 0; idx < size; idx++) { - int orderId = readOrderId(methodScope); - Node value = ensureNodeCreated(methodScope, loopScope, orderId); - nodeList.initialize(idx, value); - if (updateUsages && value != null && !value.isDeleted()) { - edges.update(node, null, value); + } + } + + protected void makeFloatingNodeInputs(MethodScope methodScope, LoopScope loopScope, Node node) { + Edges edges = node.getNodeClass().getInputEdges(); + if (node instanceof PhiNode) { + /* + * The inputs of phi functions are filled manually when the end nodes are processed. + * However, the values must not be null, so initialize them with an empty list. + */ + assert edges.getDirectCount() == 1 : "PhiNode has one direct input (the MergeNode)"; + assert edges.getCount() - edges.getDirectCount() == 1 : "PhiNode has one variable size input (the values)"; + edges.initializeList(node, edges.getDirectCount(), new NodeInputList<>(node)); + } else { + for (int index = 0; index < edges.getDirectCount(); index++) { + int orderId = readOrderId(methodScope); + Node value = ensureNodeCreated(methodScope, loopScope, orderId); + edges.initializeNode(node, index, value); + } + for (int index = edges.getDirectCount(); index < edges.getCount(); index++) { + int size = methodScope.reader.getSVInt(); + if (size != -1) { + NodeList<Node> nodeList = new NodeInputList<>(node, size); + edges.initializeList(node, index, nodeList); + for (int idx = 0; idx < size; idx++) { + int orderId = readOrderId(methodScope); + Node value = ensureNodeCreated(methodScope, loopScope, orderId); + nodeList.initialize(idx, value); } } } @@ -1024,31 +1077,34 @@ } node = decodeFloatingNode(methodScope, loopScope, nodeOrderId); - if (node instanceof ProxyNode || node instanceof PhiNode) { /* * We need these nodes as they were in the original graph, without any canonicalization * or value numbering. */ - node = methodScope.graph.addWithoutUnique(node); + node = graph.addWithoutUnique(node); } else { /* Allow subclasses to canonicalize and intercept nodes. */ - node = handleFloatingNodeBeforeAdd(methodScope, loopScope, node); - if (!node.isAlive()) { - node = addFloatingNode(methodScope, node); + Node newNode = handleFloatingNodeBeforeAdd(methodScope, loopScope, node); + if (newNode != node) { + releaseFloatingNode(node); } - node = handleFloatingNodeAfterAdd(methodScope, loopScope, node); + + if (!newNode.isAlive()) { + newNode = addFloatingNode(methodScope, newNode); + } + node = handleFloatingNodeAfterAdd(methodScope, loopScope, newNode); } registerNode(loopScope, nodeOrderId, node, false, false); return node; } - protected Node addFloatingNode(MethodScope methodScope, Node node) { + protected Node addFloatingNode(@SuppressWarnings("unused") MethodScope methodScope, Node node) { /* * We want to exactly reproduce the encoded graph. Even though nodes should be unique in the * encoded graph, this is not always guaranteed. */ - return methodScope.graph.addWithoutUnique(node); + return graph.addWithoutUnique(node); } /** @@ -1056,7 +1112,10 @@ */ protected Node decodeFloatingNode(MethodScope methodScope, LoopScope loopScope, int nodeOrderId) { long readerByteIndex = methodScope.reader.getByteIndex(); - Node node = instantiateNode(methodScope, nodeOrderId); + + methodScope.reader.setByteIndex(methodScope.encodedGraph.nodeStartOffsets[nodeOrderId]); + NodeClass<?> nodeClass = methodScope.encodedGraph.getNodeClasses()[methodScope.reader.getUVInt()]; + Node node = allocateFloatingNode(nodeClass); if (node instanceof FixedNode) { /* * This is a severe error that will lead to a corrupted graph, so it is better not to @@ -1065,16 +1124,38 @@ throw shouldNotReachHere("Not a floating node: " + node.getClass().getName()); } + /* Read the inputs of the node, possibly creating them recursively. */ + makeFloatingNodeInputs(methodScope, loopScope, node); + /* Read the properties of the node. */ readProperties(methodScope, node); /* There must not be any successors to read, since it is a non-fixed node. */ assert node.getNodeClass().getEdges(Edges.Type.Successors).getCount() == 0; - /* Read the inputs of the node, possibly creating them recursively. */ - makeInputNodes(methodScope, loopScope, node, false); + methodScope.reader.setByteIndex(readerByteIndex); return node; } + private Node allocateFloatingNode(NodeClass<?> nodeClass) { + ArrayDeque<? extends Node> cachedNodes = reusableFloatingNodes.get(nodeClass); + if (cachedNodes != null) { + Node node = cachedNodes.poll(); + if (node != null) { + return node; + } + } + return nodeClass.allocateInstance(); + } + + private void releaseFloatingNode(Node node) { + ArrayDeque<Node> cachedNodes = reusableFloatingNodes.get(node.getNodeClass()); + if (cachedNodes == null) { + cachedNodes = new ArrayDeque<>(2); + reusableFloatingNodes.put(node.getNodeClass(), cachedNodes); + } + cachedNodes.push(node); + } + /** * Hook for subclasses to process a non-fixed node before it is added to the graph. * @@ -1121,9 +1202,6 @@ } } for (int index = edges.getDirectCount(); index < edges.getCount(); index++) { - if (skipIndirectEdge(node, edges, index, true)) { - continue; - } int size = methodScope.reader.getSVInt(); if (size != -1) { NodeList<Node> nodeList = new NodeSuccessorList<>(node, size); @@ -1150,7 +1228,9 @@ } long readerByteIndex = methodScope.reader.getByteIndex(); - node = (FixedNode) methodScope.graph.add(instantiateNode(methodScope, nodeOrderId)); + methodScope.reader.setByteIndex(methodScope.encodedGraph.nodeStartOffsets[nodeOrderId]); + NodeClass<?> nodeClass = methodScope.encodedGraph.getNodeClasses()[methodScope.reader.getUVInt()]; + node = (FixedNode) graph.add(nodeClass.allocateInstance()); /* Properties and edges are not filled yet, the node remains uninitialized. */ methodScope.reader.setByteIndex(readerByteIndex); @@ -1174,12 +1254,6 @@ return true; } } - } else if (node instanceof PhiNode) { - /* The inputs of phi functions are filled manually when the end nodes are processed. */ - assert edges.type() == Edges.Type.Inputs; - assert index == edges.getDirectCount() - 1 : "PhiNode has one direct input (the MergeNode)"; - return true; - } else if (node instanceof LoopExitNode && edges.type() == Edges.Type.Inputs && edges.getType(index) == FrameState.class) { /* The stateAfter of the loop exit is filled manually. */ return true; @@ -1188,29 +1262,6 @@ return false; } - protected static boolean skipIndirectEdge(Node node, Edges edges, int index, boolean decode) { - assert !(node instanceof Invoke); - assert !(node instanceof LoopExitNode && edges.type() == Edges.Type.Inputs && edges.getType(index) == FrameState.class); - if (node instanceof AbstractMergeNode && edges.type() == Edges.Type.Inputs) { - /* The ends of merge nodes are filled manually when the ends are processed. */ - assert index == edges.getCount() - 1 : "MergeNode has one variable size input (the ends)"; - assert Edges.getNodeList(node, edges.getOffsets(), index) != null : "Input list must have been already created"; - return true; - - } else if (node instanceof PhiNode) { - /* The inputs of phi functions are filled manually when the end nodes are processed. */ - assert edges.type() == Edges.Type.Inputs; - assert index == edges.getCount() - 1 : "PhiNode has one variable size input (the values)"; - if (decode) { - /* The values must not be null, so initialize with an empty list. */ - edges.initializeList(node, index, new NodeInputList<>(node)); - } - return true; - - } - return false; - } - protected Node lookupNode(LoopScope loopScope, int nodeOrderId) { return loopScope.createdNodes[nodeOrderId]; } @@ -1236,11 +1287,11 @@ * @param methodScope The current method. */ protected void cleanupGraph(MethodScope methodScope) { - assert verifyEdges(methodScope); + assert verifyEdges(); } - protected boolean verifyEdges(MethodScope methodScope) { - for (Node node : methodScope.graph.getNodes()) { + protected boolean verifyEdges() { + for (Node node : graph.getNodes()) { assert node.isAlive(); for (Node i : node.inputs()) { assert i.isAlive(); @@ -1278,7 +1329,7 @@ * The ends, i.e., the source of backward branches. The {@link EndNode#successors successor} * is the {@link #header loop header}. */ - List<EndNode> ends = new ArrayList<>(); + List<EndNode> ends = new ArrayList<>(2); /** * Exits of the loop. The successor is a {@link MergeNode} marked in * {@link MethodScope#loopExplosionMerges}. @@ -1291,20 +1342,20 @@ boolean irreducible; } + private final StructuredGraph graph; private final MethodScope methodScope; - private final FixedNode startInstruction; private Loop irreducibleLoopHandler; private IntegerSwitchNode irreducibleLoopSwitch; - protected LoopDetector(MethodScope methodScope, FixedNode startInstruction) { + protected LoopDetector(StructuredGraph graph, MethodScope methodScope) { + this.graph = graph; this.methodScope = methodScope; - this.startInstruction = startInstruction; } @Override public void run() { - Debug.dump(Debug.VERBOSE_LOG_LEVEL, methodScope.graph, "Before loop detection"); + Debug.dump(Debug.DETAILED_LEVEL, graph, "Before loop detection"); List<Loop> orderedLoops = findLoops(); assert orderedLoops.get(orderedLoops.size() - 1) == irreducibleLoopHandler : "outermost loop must be the last element in the list"; @@ -1327,11 +1378,11 @@ } else { insertLoopNodes(loop); } - Debug.dump(Debug.VERBOSE_LOG_LEVEL, methodScope.graph, "After handling of loop %s", loop.header); + Debug.dump(Debug.DETAILED_LEVEL, graph, "After handling of loop %s", loop.header); } logIrreducibleLoops(); - Debug.dump(Debug.VERBOSE_LOG_LEVEL, methodScope.graph, "After loop detection"); + Debug.dump(Debug.DETAILED_LEVEL, graph, "After loop detection"); } private List<Loop> findLoops() { @@ -1346,11 +1397,11 @@ */ irreducibleLoopHandler = findOrCreateLoop(unorderedLoops, methodScope.loopExplosionHead); - NodeBitMap visited = methodScope.graph.createNodeBitMap(); - NodeBitMap active = methodScope.graph.createNodeBitMap(); + NodeBitMap visited = graph.createNodeBitMap(); + NodeBitMap active = graph.createNodeBitMap(); Deque<Node> stack = new ArrayDeque<>(); - visited.mark(startInstruction); - stack.push(startInstruction); + visited.mark(methodScope.loopExplosionHead); + stack.push(methodScope.loopExplosionHead); while (!stack.isEmpty()) { Node current = stack.peek(); @@ -1421,7 +1472,7 @@ */ List<Node> possibleExits = new ArrayList<>(); - NodeBitMap visited = methodScope.graph.createNodeBitMap(); + NodeBitMap visited = graph.createNodeBitMap(); Deque<Node> stack = new ArrayDeque<>(); for (EndNode loopEnd : loop.ends) { stack.push(loopEnd); @@ -1433,7 +1484,7 @@ if (current == loop.header) { continue; } - if (!methodScope.graph.isNew(methodScope.methodStartMark, current)) { + if (!graph.isNew(methodScope.methodStartMark, current)) { /* * The current node is before the method that contains the exploded loop. The loop * must have a second entry point, i.e., it is an irreducible loop. @@ -1498,7 +1549,6 @@ * necessary into a loop because it computes loop information based on bytecodes, before the * actual parsing. */ - for (Node succ : possibleExits) { if (!visited.contains(succ)) { stack.push(succ); @@ -1541,8 +1591,8 @@ FrameState stateAfter = merge.stateAfter().duplicate(); FixedNode afterMerge = merge.next(); merge.setNext(null); - EndNode preLoopEnd = methodScope.graph.add(new EndNode()); - LoopBeginNode loopBegin = methodScope.graph.add(new LoopBeginNode()); + EndNode preLoopEnd = graph.add(new EndNode()); + LoopBeginNode loopBegin = graph.add(new LoopBeginNode()); merge.setNext(preLoopEnd); /* Add the single non-loop predecessor of the loop header. */ @@ -1559,7 +1609,7 @@ List<PhiNode> loopBeginPhis = new ArrayList<>(mergePhis.size()); for (int i = 0; i < mergePhis.size(); i++) { PhiNode mergePhi = mergePhis.get(i); - PhiNode loopBeginPhi = methodScope.graph.addWithoutUnique(new ValuePhiNode(mergePhi.stamp(), loopBegin)); + PhiNode loopBeginPhi = graph.addWithoutUnique(new ValuePhiNode(mergePhi.stamp(), loopBegin)); mergePhi.replaceAtUsages(loopBeginPhi); /* * The first input of the new phi function is the original phi function, for the one @@ -1577,7 +1627,7 @@ } merge.removeEnd(endNode); - LoopEndNode loopEnd = methodScope.graph.add(new LoopEndNode(loopBegin)); + LoopEndNode loopEnd = graph.add(new LoopEndNode(loopBegin)); endNode.replaceAndDelete(loopEnd); } @@ -1589,7 +1639,7 @@ AbstractMergeNode loopExplosionMerge = exit.merge(); assert methodScope.loopExplosionMerges.contains(loopExplosionMerge); - LoopExitNode loopExit = methodScope.graph.add(new LoopExitNode(loopBegin)); + LoopExitNode loopExit = graph.add(new LoopExitNode(loopBegin)); exit.replaceAtPredecessor(loopExit); loopExit.setNext(exit); assignLoopExitState(loopExit, loopExplosionMerge, exit); @@ -1630,7 +1680,7 @@ realValue = ProxyPlaceholder.unwrap(value); } - if (realValue == null || realValue.isConstant() || loopBeginValues.contains(realValue) || !methodScope.graph.isNew(methodScope.methodStartMark, realValue)) { + if (realValue == null || realValue.isConstant() || loopBeginValues.contains(realValue) || !graph.isNew(methodScope.methodStartMark, realValue)) { newValues.add(realValue); } else { /* @@ -1641,7 +1691,7 @@ "Value flowing out of loop, but we are not prepared to insert a ProxyNode"); ProxyPlaceholder proxyPlaceholder = (ProxyPlaceholder) value; - ValueProxyNode proxy = ProxyNode.forValue(proxyPlaceholder.value, loopExit, methodScope.graph); + ValueProxyNode proxy = ProxyNode.forValue(proxyPlaceholder.value, loopExit, graph); proxyPlaceholder.setValue(proxy); newValues.add(proxy); } @@ -1651,7 +1701,7 @@ oldState.duringCall(), oldState.monitorIds(), oldState.virtualObjectMappings()); assert loopExit.stateAfter() == null; - loopExit.setStateAfter(methodScope.graph.add(newState)); + loopExit.setStateAfter(graph.add(newState)); } /** @@ -1722,7 +1772,7 @@ assert irreducibleLoopHandler.header.phis().isEmpty(); /* The new phi function for the loop variable. */ - loopVariablePhi = methodScope.graph.addWithoutUnique(new ValuePhiNode(explosionHeadValue.stamp().unrestricted(), irreducibleLoopHandler.header)); + loopVariablePhi = graph.addWithoutUnique(new ValuePhiNode(explosionHeadValue.stamp().unrestricted(), irreducibleLoopHandler.header)); for (int i = 0; i < irreducibleLoopHandler.header.phiPredecessorCount(); i++) { loopVariablePhi.addInput(explosionHeadValue); } @@ -1732,7 +1782,7 @@ * to the old FrameState: the loop variable is replaced with the phi function. */ FrameState oldFrameState = explosionHeadState; - List<ValueNode> newFrameStateValues = new ArrayList<>(); + List<ValueNode> newFrameStateValues = new ArrayList<>(explosionHeadValues.size()); for (int i = 0; i < explosionHeadValues.size(); i++) { if (i == loopVariableIndex) { newFrameStateValues.add(loopVariablePhi); @@ -1740,7 +1790,8 @@ newFrameStateValues.add(explosionHeadValues.get(i)); } } - FrameState newFrameState = methodScope.graph.add( + + FrameState newFrameState = graph.add( new FrameState(oldFrameState.outerFrameState(), oldFrameState.getCode(), oldFrameState.bci, newFrameStateValues, oldFrameState.localsSize(), oldFrameState.stackSize(), oldFrameState.rethrowException(), oldFrameState.duringCall(), oldFrameState.monitorIds(), oldFrameState.virtualObjectMappings())); @@ -1752,7 +1803,7 @@ */ FixedNode handlerNext = irreducibleLoopHandler.header.next(); irreducibleLoopHandler.header.setNext(null); - BeginNode handlerBegin = methodScope.graph.add(new BeginNode()); + BeginNode handlerBegin = graph.add(new BeginNode()); handlerBegin.setNext(handlerNext); dispatchTable.put(asInt(explosionHeadValue), handlerBegin); @@ -1760,8 +1811,8 @@ * We know that there will always be a matching key in the switch. But Graal always * wants a default successor, so we build a dummy block that just deoptimizes. */ - unreachableDefaultSuccessor = methodScope.graph.add(new BeginNode()); - DeoptimizeNode deopt = methodScope.graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode)); + unreachableDefaultSuccessor = graph.add(new BeginNode()); + DeoptimizeNode deopt = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode)); unreachableDefaultSuccessor.setNext(deopt); } else { @@ -1796,8 +1847,8 @@ /* Insert our loop into the dispatch state machine. */ assert loop.header.phis().isEmpty(); - BeginNode dispatchBegin = methodScope.graph.add(new BeginNode()); - EndNode dispatchEnd = methodScope.graph.add(new EndNode()); + BeginNode dispatchBegin = graph.add(new BeginNode()); + EndNode dispatchEnd = graph.add(new EndNode()); dispatchBegin.setNext(dispatchEnd); loop.header.addForwardEnd(dispatchEnd); int intLoopValue = asInt(loopValue); @@ -1813,7 +1864,7 @@ } /* Build and insert the switch node. */ - irreducibleLoopSwitch = methodScope.graph.add(createSwitch(loopVariablePhi, dispatchTable, unreachableDefaultSuccessor)); + irreducibleLoopSwitch = graph.add(createSwitch(loopVariablePhi, dispatchTable, unreachableDefaultSuccessor)); irreducibleLoopHandler.header.setNext(irreducibleLoopSwitch); } @@ -1859,14 +1910,14 @@ @SuppressWarnings("try") private void logIrreducibleLoops() { try (Debug.Scope s = Debug.scope("IrreducibleLoops")) { - if (Debug.isLogEnabled(Debug.BASIC_LOG_LEVEL) && irreducibleLoopSwitch != null) { + if (Debug.isLogEnabled(Debug.BASIC_LEVEL) && irreducibleLoopSwitch != null) { StringBuilder msg = new StringBuilder("Inserted state machine to remove irreducible loops. Dispatching to the following states: "); String sep = ""; for (int i = 0; i < irreducibleLoopSwitch.keyCount(); i++) { msg.append(sep).append(irreducibleLoopSwitch.keyAt(i).asInt()); sep = ", "; } - Debug.log(Debug.BASIC_LOG_LEVEL, "%s", msg); + Debug.log(Debug.BASIC_LEVEL, "%s", msg); } } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java Thu Apr 06 23:01:27 2017 +0000 @@ -67,10 +67,11 @@ * encoding-local. * * The encoded graph has the following structure: First, all nodes and their edges are serialized. - * The start offset of every node is then known. The raw node data is followed by a "table of - * contents" that lists the start offset for every node. + * The start offset of every node is then known. The raw node data is followed by metadata, i.e., + * the maximum fixed node order id and a "table of contents" that lists the start offset for every + * node. * - * The beginning of that table of contents is the return value of {@link #encode} and stored in + * The beginning of this metadata is the return value of {@link #encode} and stored in * {@link EncodedGraph#getStartOffset()}. The order of nodes in the table of contents is the * {@link NodeOrder#orderIds orderId} of a node. Note that the orderId is not the regular node id * that every Graal graph node gets assigned. The orderId is computed and used just for encoding and @@ -85,8 +86,8 @@ * <pre> * struct Node { * unsigned typeId + * unsigned[] inputOrderIds * signed[] properties - * unsigned[] inputOrderIds * unsigned[] successorOrderIds * } * </pre> @@ -168,9 +169,8 @@ */ public void prepare(StructuredGraph graph) { for (Node node : graph.getNodes()) { - nodeClasses.addObject(node.getNodeClass()); - - NodeClass<?> nodeClass = node.getNodeClass(); + NodeClass<? extends Node> nodeClass = node.getNodeClass(); + nodeClasses.addObject(nodeClass); objects.addObject(node.getNodeSourcePosition()); for (int i = 0; i < nodeClass.getData().getCount(); i++) { if (!nodeClass.getData().getType(i).isPrimitive()) { @@ -223,8 +223,8 @@ /* Write out the type, properties, and edges. */ NodeClass<?> nodeClass = node.getNodeClass(); writer.putUV(nodeClasses.getIndex(nodeClass)); + writeEdges(node, nodeClass.getEdges(Edges.Type.Inputs), nodeOrder); writeProperties(node, nodeClass.getData()); - writeEdges(node, nodeClass.getEdges(Edges.Type.Inputs), nodeOrder); writeEdges(node, nodeClass.getEdges(Edges.Type.Successors), nodeOrder); /* Special handling for some nodes that require additional information for decoding. */ @@ -276,18 +276,23 @@ } } - /* Write out the table of contents with the start offset for all nodes. */ - int nodeTableStart = TypeConversion.asS4(writer.getBytesWritten()); + /* + * Write out the metadata (maximum fixed node order id and the table of contents with the + * start offset for all nodes). + */ + int metadataStart = TypeConversion.asS4(writer.getBytesWritten()); + writer.putUV(nodeOrder.maxFixedNodeOrderId); writer.putUV(nodeCount); for (int i = 0; i < nodeCount; i++) { assert i == NULL_ORDER_ID || i == START_NODE_ORDER_ID || nodeStartOffsets[i] > 0; - writer.putUV(nodeTableStart - nodeStartOffsets[i]); + writer.putUV(metadataStart - nodeStartOffsets[i]); } /* Check that the decoding of the encode graph is the same as the input. */ - assert verifyEncoding(graph, new EncodedGraph(getEncoding(), nodeTableStart, getObjects(), getNodeClasses(), graph.getAssumptions(), graph.getMethods()), architecture); + assert verifyEncoding(graph, new EncodedGraph(getEncoding(), metadataStart, getObjects(), getNodeClasses(), graph.getAssumptions(), graph.getMethods()), + architecture); - return nodeTableStart; + return metadataStart; } public byte[] getEncoding() { @@ -297,6 +302,7 @@ static class NodeOrder { protected final NodeMap<Integer> orderIds; protected int nextOrderId; + protected int maxFixedNodeOrderId; NodeOrder(StructuredGraph graph) { this.orderIds = new NodeMap<>(graph); @@ -337,6 +343,7 @@ } } while (current != null); + maxFixedNodeOrderId = nextOrderId - 1; for (Node node : graph.getNodes()) { assert (node instanceof FixedNode) == (orderIds.get(node) != null) : "all fixed nodes must be ordered: " + node; add(node); @@ -365,6 +372,11 @@ } protected void writeEdges(Node node, Edges edges, NodeOrder nodeOrder) { + if (node instanceof PhiNode) { + /* Edges are not needed for decoding, so we must not write it. */ + return; + } + for (int idx = 0; idx < edges.getDirectCount(); idx++) { if (GraphDecoder.skipDirectEdge(node, edges, idx)) { /* Edge is not needed for decoding, so we must not write it. */ @@ -373,21 +385,23 @@ Node edge = Edges.getNode(node, edges.getOffsets(), idx); writeOrderId(edge, nodeOrder); } - for (int idx = edges.getDirectCount(); idx < edges.getCount(); idx++) { - if (GraphDecoder.skipIndirectEdge(node, edges, idx, false)) { - /* Edge is not needed for decoding, so we must not write it. */ - continue; - } - NodeList<Node> edgeList = Edges.getNodeList(node, edges.getOffsets(), idx); - if (edgeList == null) { - writer.putSV(-1); - } else { - writer.putSV(edgeList.size()); - for (Node edge : edgeList) { - writeOrderId(edge, nodeOrder); + + if (node instanceof AbstractMergeNode && edges.type() == Edges.Type.Inputs) { + /* The ends of merge nodes are decoded manually when the ends are processed. */ + } else { + for (int idx = edges.getDirectCount(); idx < edges.getCount(); idx++) { + NodeList<Node> edgeList = Edges.getNodeList(node, edges.getOffsets(), idx); + if (edgeList == null) { + writer.putSV(-1); + } else { + writer.putSV(edgeList.size()); + for (Node edge : edgeList) { + writeOrderId(edge, nodeOrder); + } } } } + } protected void writeOrderId(Node node, NodeOrder nodeOrder) { @@ -405,16 +419,16 @@ @SuppressWarnings("try") public static boolean verifyEncoding(StructuredGraph originalGraph, EncodedGraph encodedGraph, Architecture architecture) { StructuredGraph decodedGraph = new StructuredGraph.Builder(originalGraph.getOptions(), AllowAssumptions.YES).method(originalGraph.method()).build(); - GraphDecoder decoder = new GraphDecoder(architecture); - decoder.decode(decodedGraph, encodedGraph); + GraphDecoder decoder = new GraphDecoder(architecture, decodedGraph); + decoder.decode(encodedGraph); decodedGraph.verify(); try { GraphComparison.verifyGraphsEqual(originalGraph, decodedGraph); } catch (Throwable ex) { try (Debug.Scope scope = Debug.scope("GraphEncoder")) { - Debug.dump(Debug.INFO_LOG_LEVEL, originalGraph, "Original Graph"); - Debug.dump(Debug.INFO_LOG_LEVEL, decodedGraph, "Decoded Graph"); + Debug.forceDump(originalGraph, "Original Graph"); + Debug.forceDump(decodedGraph, "Decoded Graph"); } throw ex; }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardedValueNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardedValueNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -87,7 +87,7 @@ if (stamp().equals(object().stamp())) { return object(); } else { - return new PiNode(object(), stamp()); + return PiNode.create(object(), stamp()); } } return this;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -316,7 +316,10 @@ FixedWithNextNode falseNext = (FixedWithNextNode) falseSucc.next(); NodeClass<?> nodeClass = trueNext.getNodeClass(); if (trueNext.getClass() == falseNext.getClass()) { - if (nodeClass.equalInputs(trueNext, falseNext) && trueNext.valueEquals(falseNext)) { + if (trueNext instanceof AbstractBeginNode) { + // Cannot do this optimization for begin nodes, because it could + // move guards above the if that need to stay below a branch. + } else if (nodeClass.equalInputs(trueNext, falseNext) && trueNext.valueEquals(falseNext)) { falseNext.replaceAtUsages(trueNext); graph().removeFixed(falseNext); GraphUtil.unlinkFixedNode(trueNext); @@ -600,7 +603,7 @@ protected void removeThroughFalseBranch(SimplifierTool tool) { AbstractBeginNode trueBegin = trueSuccessor(); - graph().removeSplitPropagate(this, trueBegin, tool); + graph().removeSplitPropagate(this, trueBegin); tool.addToWorkList(trueBegin); if (condition() != null) { GraphUtil.tryKillUnused(condition()); @@ -772,9 +775,9 @@ transferProxies(trueSuccessor(), trueMerge); transferProxies(falseSuccessor(), falseMerge); - cleanupMerge(tool, merge); - cleanupMerge(tool, trueMerge); - cleanupMerge(tool, falseMerge); + cleanupMerge(merge); + cleanupMerge(trueMerge); + cleanupMerge(falseMerge); return true; } @@ -869,10 +872,10 @@ } } - private void cleanupMerge(SimplifierTool tool, MergeNode merge) { + private void cleanupMerge(MergeNode merge) { if (merge != null && merge.isAlive()) { if (merge.forwardEndCount() == 0) { - GraphUtil.killCFG(merge, tool); + GraphUtil.killCFG(merge); } else if (merge.forwardEndCount() == 1) { graph().reduceTrivialMerge(merge); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiArrayNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiArrayNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -26,7 +26,6 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; @@ -69,12 +68,11 @@ * snippet. */ @NodeIntrinsic(Placeholder.class) - public static native Object piArrayCast(Object object, int length); + public static native Object piArrayCastToSnippetReplaceeStamp(Object object, int length); /** - * A placeholder node in a snippet that will be replaced with an appropriate {@link PiArrayNode} - * when the snippet is instantiated. Using a placeholder means that {@link PiArrayNode} never - * needs to deal with {@link StampFactory#forNodeIntrinsic()} stamps. + * A placeholder node in a snippet that will be replaced with a {@link PiArrayNode} when the + * snippet is instantiated. */ @NodeInfo(cycles = CYCLES_0, size = SIZE_0) public static class Placeholder extends PiNode.Placeholder { @@ -88,8 +86,9 @@ } @Override - public PiNode getReplacement(Stamp stampForPi) { - return graph().addOrUnique(new PiArrayNode(object(), length, stampForPi)); + public void makeReplacement(Stamp snippetReplaceeStamp) { + PiArrayNode piArray = graph().addOrUnique(new PiArrayNode(object(), length, snippetReplaceeStamp)); + replaceAndDelete(piArray); } } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -25,7 +25,10 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; +import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; @@ -36,6 +39,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.extended.GuardingNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -70,7 +74,6 @@ protected PiNode(NodeClass<? extends PiNode> c, ValueNode object, Stamp stamp, GuardingNode guard) { super(c, stamp, guard); - assert stamp != StampFactory.forNodeIntrinsic(); this.object = object; this.piStamp = stamp; assert piStamp.isCompatible(object.stamp()) : "Object stamp not compatible to piStamp"; @@ -93,6 +96,53 @@ this(object, StampFactory.object(exactType ? TypeReference.createExactTrusted(toType) : TypeReference.createWithoutAssumptions(toType), nonNull || StampTool.isPointerNonNull(object.stamp()))); } + public static ValueNode create(ValueNode object, Stamp stamp) { + ValueNode value = canonical(object, stamp, null); + if (value != null) { + return value; + } + return new PiNode(object, stamp); + } + + public static ValueNode create(ValueNode object, Stamp stamp, ValueNode anchor) { + ValueNode value = canonical(object, stamp, (GuardingNode) anchor); + if (value != null) { + return value; + } + return new PiNode(object, stamp, anchor); + } + + public static ValueNode create(ValueNode object, ValueNode anchor) { + Stamp stamp = AbstractPointerStamp.pointerNonNull(object.stamp()); + ValueNode value = canonical(object, stamp, (GuardingNode) anchor); + if (value != null) { + return value; + } + return new PiNode(object, stamp, anchor); + } + + @SuppressWarnings("unused") + public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode object, ValueNode anchor) { + Stamp stamp = AbstractPointerStamp.pointerNonNull(object.stamp()); + ValueNode value = canonical(object, stamp, (GuardingNode) anchor); + if (value == null) { + value = new PiNode(object, stamp, anchor); + } + b.push(JavaKind.Object, b.recursiveAppend(value)); + return true; + } + + @SuppressWarnings("unused") + public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { + Stamp stamp = StampFactory.object(exactType ? TypeReference.createExactTrusted(toType) : TypeReference.createWithoutAssumptions(toType), nonNull || StampTool.isPointerNonNull(object.stamp())); + ValueNode value = canonical(object, stamp, null); + if (value == null) { + value = new PiNode(object, stamp); + } + b.push(JavaKind.Object, b.recursiveAppend(value)); + return true; + } + public final Stamp piStamp() { return piStamp; } @@ -124,37 +174,32 @@ } } - @Override - public Node canonical(CanonicalizerTool tool) { + public static ValueNode canonical(ValueNode object, Stamp stamp, GuardingNode guard) { // Use most up to date stamp. - Stamp computedStamp = computeStamp(); - - ValueNode o = object(); + Stamp computedStamp = stamp.improveWith(object.stamp()); // The pi node does not give any additional information => skip it. - if (computedStamp.equals(o.stamp())) { - return o; + if (computedStamp.equals(object.stamp())) { + return object; } - GuardingNode g = getGuard(); - if (g == null) { - + if (guard == null) { // Try to merge the pi node with a load node. - if (o instanceof ReadNode) { - ReadNode readNode = (ReadNode) o; - readNode.setStamp(readNode.stamp().improveWith(this.piStamp)); + if (object instanceof ReadNode) { + ReadNode readNode = (ReadNode) object; + readNode.setStamp(readNode.stamp().improveWith(stamp)); return readNode; } } else { - for (Node n : g.asNode().usages()) { + for (Node n : guard.asNode().usages()) { if (n instanceof PiNode) { PiNode otherPi = (PiNode) n; - if (o == otherPi.object() && computedStamp.equals(otherPi.stamp())) { + if (object == otherPi.object() && computedStamp.equals(otherPi.stamp())) { /* * Two PiNodes with the same guard and same result, so return the one with * the more precise piStamp. */ - Stamp newStamp = piStamp.join(otherPi.piStamp); + Stamp newStamp = stamp.join(otherPi.piStamp); if (newStamp.equals(otherPi.piStamp)) { return otherPi; } @@ -162,6 +207,15 @@ } } } + return null; + } + + @Override + public Node canonical(CanonicalizerTool tool) { + Node value = canonical(object(), stamp(), getGuard()); + if (value != null) { + return value; + } return this; } @@ -226,9 +280,8 @@ public static native Object piCast(Object object, @ConstantNodeParameter Class<?> toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull); /** - * A placeholder node in a snippet that will be replaced with an appropriate {@link PiNode} when - * the snippet is instantiated. Using a placeholder means that {@link PiNode} never needs to - * deal with {@link StampFactory#forNodeIntrinsic()} stamps. + * A placeholder node in a snippet that will be replaced with a {@link PiNode} when the snippet + * is instantiated. */ @NodeInfo(cycles = CYCLES_0, size = SIZE_0) public static class Placeholder extends FloatingGuardedNode { @@ -241,7 +294,7 @@ } protected Placeholder(NodeClass<? extends Placeholder> c, ValueNode object) { - super(c, StampFactory.forNodeIntrinsic(), null); + super(c, PlaceholderStamp.SINGLETON, null); this.object = object; } @@ -250,12 +303,44 @@ } /** - * Gets a new {@link PiNode} that replaces this placeholder during snippet instantiation. + * Replaces this node with a {@link PiNode} during snippet instantiation. * * @param snippetReplaceeStamp the stamp of the node being replace by the snippet */ - public PiNode getReplacement(Stamp snippetReplaceeStamp) { - return graph().addOrUnique(new PiNode(object(), snippetReplaceeStamp, null)); + public void makeReplacement(Stamp snippetReplaceeStamp) { + ValueNode value = graph().maybeAddOrUnique(PiNode.create(object(), snippetReplaceeStamp, null)); + replaceAndDelete(value); + } + } + + /** + * A stamp for {@link Placeholder} nodes which are only used in snippets. It is replaced by an + * actual stamp when the snippet is instantiated. + */ + public static final class PlaceholderStamp extends ObjectStamp { + private static final PlaceholderStamp SINGLETON = new PlaceholderStamp(); + + public static PlaceholderStamp singleton() { + return SINGLETON; + } + + private PlaceholderStamp() { + super(null, false, false, false); + } + + @Override + public int hashCode() { + return System.identityHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return this == obj; + } + + @Override + public String toString() { + return "PlaceholderStamp"; } } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java Thu Apr 06 23:01:27 2017 +0000 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.nodes; +import static org.graalvm.compiler.nodeinfo.InputType.Guard; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; @@ -37,6 +38,9 @@ import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; +import org.graalvm.compiler.nodes.java.ArrayLengthNode; +import org.graalvm.compiler.nodes.java.LoadFieldNode; +import org.graalvm.compiler.nodes.java.LoadIndexedNode; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.OptionValues; @@ -59,6 +63,7 @@ protected final ConstantFieldProvider constantFieldProvider; protected final StampProvider stampProvider; protected final boolean canonicalizeReads; + protected final CanonicalizerTool canonicalizerTool; protected class PECanonicalizerTool implements CanonicalizerTool { @@ -113,7 +118,7 @@ } } - @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) + @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED, allowedUsageTypes = {Guard}) static class CanonicalizeToNullNode extends FloatingNode implements Canonicalizable, GuardingNode { public static final NodeClass<CanonicalizeToNullNode> TYPE = NodeClass.create(CanonicalizeToNullNode.class); @@ -127,32 +132,30 @@ } } - public SimplifyingGraphDecoder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, StampProvider stampProvider, - boolean canonicalizeReads, Architecture architecture) { - super(architecture); + public SimplifyingGraphDecoder(Architecture architecture, StructuredGraph graph, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, + ConstantFieldProvider constantFieldProvider, StampProvider stampProvider, + boolean canonicalizeReads) { + super(architecture, graph); this.metaAccess = metaAccess; this.constantReflection = constantReflection; this.constantFieldProvider = constantFieldProvider; this.stampProvider = stampProvider; this.canonicalizeReads = canonicalizeReads; + this.canonicalizerTool = new PECanonicalizerTool(graph.getAssumptions(), graph.getOptions()); } @Override protected void cleanupGraph(MethodScope methodScope) { - GraphUtil.normalizeLoops(methodScope.graph); + GraphUtil.normalizeLoops(graph); super.cleanupGraph(methodScope); - for (Node node : methodScope.graph.getNewNodes(methodScope.methodStartMark)) { + for (Node node : graph.getNewNodes(methodScope.methodStartMark)) { if (node instanceof MergeNode) { MergeNode mergeNode = (MergeNode) node; if (mergeNode.forwardEndCount() == 1) { - methodScope.graph.reduceTrivialMerge(mergeNode); + graph.reduceTrivialMerge(mergeNode); } - } - } - - for (Node node : methodScope.graph.getNewNodes(methodScope.methodStartMark)) { - if (node instanceof BeginNode || node instanceof KillingBeginNode) { + } else if (node instanceof BeginNode || node instanceof KillingBeginNode) { if (!(node.predecessor() instanceof ControlSplitNode) && node.hasNoUsages()) { GraphUtil.unlinkFixedNode((AbstractBeginNode) node); node.safeDelete(); @@ -160,7 +163,7 @@ } } - for (Node node : methodScope.graph.getNewNodes(methodScope.methodStartMark)) { + for (Node node : graph.getNewNodes(methodScope.methodStartMark)) { GraphUtil.tryKillUnused(node); } } @@ -187,7 +190,32 @@ @Override protected void handleFixedNode(MethodScope methodScope, LoopScope loopScope, int nodeOrderId, FixedNode node) { - if (node instanceof IfNode) { + Node canonical = canonicalizeFixedNode(node); + if (canonical != node) { + handleCanonicalization(loopScope, nodeOrderId, node, canonical); + } + } + + private Node canonicalizeFixedNode(FixedNode node) { + if (node instanceof LoadFieldNode) { + LoadFieldNode loadFieldNode = (LoadFieldNode) node; + return loadFieldNode.canonical(canonicalizerTool); + } else if (node instanceof FixedGuardNode) { + FixedGuardNode guard = (FixedGuardNode) node; + if (guard.getCondition() instanceof LogicConstantNode) { + LogicConstantNode condition = (LogicConstantNode) guard.getCondition(); + if (condition.getValue() == guard.isNegated()) { + DeoptimizeNode deopt = new DeoptimizeNode(guard.getAction(), guard.getReason(), guard.getSpeculation()); + if (guard.stateBefore() != null) { + deopt.setStateBefore(guard.stateBefore()); + } + return deopt; + } else { + return null; + } + } + return node; + } else if (node instanceof IfNode) { IfNode ifNode = (IfNode) node; if (ifNode.condition() instanceof LogicNegationNode) { ifNode.eliminateNegation(); @@ -197,73 +225,55 @@ AbstractBeginNode survivingSuccessor = ifNode.getSuccessor(condition); AbstractBeginNode deadSuccessor = ifNode.getSuccessor(!condition); - methodScope.graph.removeSplit(ifNode, survivingSuccessor); + graph.removeSplit(ifNode, survivingSuccessor); assert deadSuccessor.next() == null : "must not be parsed yet"; deadSuccessor.safeDelete(); } - + return node; + } else if (node instanceof LoadIndexedNode) { + LoadIndexedNode loadIndexedNode = (LoadIndexedNode) node; + return loadIndexedNode.canonical(canonicalizerTool); + } else if (node instanceof ArrayLengthNode) { + ArrayLengthNode arrayLengthNode = (ArrayLengthNode) node; + return arrayLengthNode.canonical(canonicalizerTool); } else if (node instanceof IntegerSwitchNode && ((IntegerSwitchNode) node).value().isConstant()) { IntegerSwitchNode switchNode = (IntegerSwitchNode) node; int value = switchNode.value().asJavaConstant().asInt(); AbstractBeginNode survivingSuccessor = switchNode.successorAtKey(value); List<Node> allSuccessors = switchNode.successors().snapshot(); - methodScope.graph.removeSplit(switchNode, survivingSuccessor); + graph.removeSplit(switchNode, survivingSuccessor); for (Node successor : allSuccessors) { if (successor != survivingSuccessor) { assert ((AbstractBeginNode) successor).next() == null : "must not be parsed yet"; successor.safeDelete(); } } - - } else if (node instanceof FixedGuardNode) { - FixedGuardNode guard = (FixedGuardNode) node; - if (guard.getCondition() instanceof LogicConstantNode) { - LogicConstantNode condition = (LogicConstantNode) guard.getCondition(); - Node canonical; - if (condition.getValue() == guard.isNegated()) { - DeoptimizeNode deopt = new DeoptimizeNode(guard.getAction(), guard.getReason(), guard.getSpeculation()); - if (guard.stateBefore() != null) { - deopt.setStateBefore(guard.stateBefore()); - } - canonical = deopt; - } else { - /* - * The guard is unnecessary, but we cannot remove the node completely yet - * because there might be nodes that use it as a guard input. Therefore, we - * replace it with a more lightweight node (which is floating and has no - * inputs). - */ - canonical = new CanonicalizeToNullNode(node.stamp); - } - handleCanonicalization(methodScope, loopScope, nodeOrderId, node, canonical); - } - + return node; } else if (node instanceof Canonicalizable) { - Node canonical = ((Canonicalizable) node).canonical(new PECanonicalizerTool(methodScope.graph.getAssumptions(), methodScope.graph.getOptions())); - if (canonical != node) { - handleCanonicalization(methodScope, loopScope, nodeOrderId, node, canonical); - } + return ((Canonicalizable) node).canonical(canonicalizerTool); + } else { + return node; } } - private void handleCanonicalization(MethodScope methodScope, LoopScope loopScope, int nodeOrderId, FixedNode node, Node c) { - Node canonical = c; + private static Node canonicalizeFixedNodeToNull(FixedNode node) { + /* + * When a node is unnecessary, we must not remove it right away because there might be nodes + * that use it as a guard input. Therefore, we replace it with a more lightweight node + * (which is floating and has no inputs). + */ + return new CanonicalizeToNullNode(node.stamp); + } - if (canonical == null) { - /* - * This is a possible return value of canonicalization. However, we might need to add - * additional usages later on for which we need a node. Therefore, we just do nothing - * and leave the node in place. - */ - return; - } - + private void handleCanonicalization(LoopScope loopScope, int nodeOrderId, FixedNode node, Node c) { + assert c != node : "unnecessary call"; + Node canonical = c == null ? canonicalizeFixedNodeToNull(node) : c; if (!canonical.isAlive()) { assert !canonical.isDeleted(); - canonical = methodScope.graph.addOrUniqueWithInputs(canonical); + canonical = graph.addOrUniqueWithInputs(canonical); if (canonical instanceof FixedWithNextNode) { - methodScope.graph.addBeforeFixed(node, (FixedWithNextNode) canonical); + graph.addBeforeFixed(node, (FixedWithNextNode) canonical); } else if (canonical instanceof ControlSinkNode) { FixedWithNextNode predecessor = (FixedWithNextNode) node.predecessor(); predecessor.setNext((ControlSinkNode) canonical); @@ -291,7 +301,7 @@ ((ValueNode) node).inferStamp(); } if (node instanceof Canonicalizable) { - Node canonical = ((Canonicalizable) node).canonical(new PECanonicalizerTool(methodScope.graph.getAssumptions(), methodScope.graph.getOptions())); + Node canonical = ((Canonicalizable) node).canonical(canonicalizerTool); if (canonical == null) { /* * This is a possible return value of canonicalization. However, we might need to @@ -301,10 +311,9 @@ } else if (canonical != node) { if (!canonical.isAlive()) { assert !canonical.isDeleted(); - canonical = methodScope.graph.addOrUniqueWithInputs(canonical); + canonical = graph.addOrUniqueWithInputs(canonical); } assert node.hasNoUsages(); - // methodScope.graph.replaceFloating((FloatingNode) node, canonical); return canonical; } } @@ -317,6 +326,6 @@ * In contrast to the base class implementation, we do not need to exactly reproduce the * encoded graph. Since we do canonicalization, we also want nodes to be unique. */ - return methodScope.graph.addOrUnique(node); + return graph.addOrUnique(node); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Thu Apr 06 23:01:27 2017 +0000 @@ -37,7 +37,6 @@ import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; -import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; @@ -553,12 +552,8 @@ node.safeDelete(); } + @SuppressWarnings("static-method") public void removeSplitPropagate(ControlSplitNode node, AbstractBeginNode survivingSuccessor) { - removeSplitPropagate(node, survivingSuccessor, null); - } - - @SuppressWarnings("static-method") - public void removeSplitPropagate(ControlSplitNode node, AbstractBeginNode survivingSuccessor, SimplifierTool tool) { assert node != null; assert node.hasNoUsages(); assert survivingSuccessor != null; @@ -569,7 +564,7 @@ for (Node successor : snapshot) { if (successor != null && successor.isAlive()) { if (successor != survivingSuccessor) { - GraphUtil.killCFG((FixedNode) successor, tool); + GraphUtil.killCFG((FixedNode) successor); } } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AddNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AddNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -57,28 +57,16 @@ ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); if (tryConstantFold != null) { return tryConstantFold; + } + if (x.isConstant() && !y.isConstant()) { + return canonical(null, op, y, x); } else { - return new AddNode(x, y).maybeCommuteInputs(); + return canonical(null, op, x, y); } } - @Override - public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - ValueNode ret = super.canonical(tool, forX, forY); - if (ret != this) { - return ret; - } - - if (forX.isConstant() && !forY.isConstant()) { - // we try to swap and canonicalize - ValueNode improvement = canonical(tool, forY, forX); - if (improvement != this) { - return improvement; - } - // if this fails we only swap - return new AddNode(forY, forX); - } - BinaryOp<Add> op = getOp(forX, forY); + private static ValueNode canonical(AddNode addNode, BinaryOp<Add> op, ValueNode forX, ValueNode forY) { + AddNode self = addNode; boolean associative = op.isAssociative(); if (associative) { if (forX instanceof SubNode) { @@ -101,10 +89,10 @@ if (op.isNeutral(c)) { return forX; } - if (associative) { + if (associative && self != null) { // canonicalize expressions like "(a + 1) + 2" - ValueNode reassociated = reassociate(this, ValueNode.isConstantPredicate(), forX, forY); - if (reassociated != this) { + ValueNode reassociated = reassociate(self, ValueNode.isConstantPredicate(), forX, forY); + if (reassociated != self) { return reassociated; } } @@ -114,7 +102,30 @@ } else if (forY instanceof NegateNode) { return BinaryArithmeticNode.sub(forX, ((NegateNode) forY).getValue()); } - return this; + if (self == null) { + self = (AddNode) new AddNode(forX, forY).maybeCommuteInputs(); + } + return self; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + ValueNode ret = super.canonical(tool, forX, forY); + if (ret != this) { + return ret; + } + + if (forX.isConstant() && !forY.isConstant()) { + // we try to swap and canonicalize + ValueNode improvement = canonical(tool, forY, forX); + if (improvement != this) { + return improvement; + } + // if this fails we only swap + return new AddNode(forY, forX); + } + BinaryOp<Add> op = getOp(forX, forY); + return canonical(this, op, forX, forY); } @Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AndNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AndNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -57,9 +57,8 @@ ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); if (tryConstantFold != null) { return tryConstantFold; - } else { - return new AndNode(x, y).maybeCommuteInputs(); } + return canonical(null, op, stamp, x, y); } @Override @@ -69,6 +68,10 @@ return ret; } + return canonical(this, getOp(forX, forY), stamp(), forX, forY); + } + + private static ValueNode canonical(AndNode self, BinaryOp<And> op, Stamp stamp, ValueNode forX, ValueNode forY) { if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { return forX; } @@ -77,15 +80,15 @@ } if (forY.isConstant()) { Constant c = forY.asConstant(); - if (getOp(forX, forY).isNeutral(c)) { + if (op.isNeutral(c)) { return forX; } if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) { long rawY = ((PrimitiveConstant) c).asLong(); - long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp())); + long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp)); if ((rawY & mask) == 0) { - return ConstantNode.forIntegerStamp(stamp(), 0); + return ConstantNode.forIntegerStamp(stamp, 0); } if (forX instanceof SignExtendNode) { SignExtendNode ext = (SignExtendNode) forX; @@ -100,9 +103,12 @@ } } - return reassociate(this, ValueNode.isConstantPredicate(), forX, forY); + return reassociate(self != null ? self : (AndNode) new AndNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY); } - return this; + if (forX instanceof NotNode && forY instanceof NotNode) { + return new NotNode(OrNode.create(((NotNode) forX).getValue(), ((NotNode) forY).getValue())); + } + return self != null ? self : new AndNode(forX, forY).maybeCommuteInputs(); } @Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -44,6 +44,7 @@ import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.PrimitiveConstant; @NodeInfo(cycles = CYCLES_1) public abstract class CompareNode extends BinaryOpLogicNode implements Canonicalizable.Binary<ValueNode> { @@ -151,12 +152,19 @@ } public static LogicNode tryConstantFold(Condition condition, ValueNode forX, ValueNode forY, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) { - if (forX.isConstant() && forY.isConstant() && constantReflection != null) { + if (forX.isConstant() && forY.isConstant() && (constantReflection != null || forX.asConstant() instanceof PrimitiveConstant)) { return LogicConstantNode.forBoolean(condition.foldCondition(forX.asConstant(), forY.asConstant(), constantReflection, unorderedIsTrue)); } return null; } + public static LogicNode tryConstantFoldPrimitive(Condition condition, ValueNode forX, ValueNode forY, boolean unorderedIsTrue) { + if (forX.asConstant() instanceof PrimitiveConstant && forY.asConstant() instanceof PrimitiveConstant) { + return LogicConstantNode.forBoolean(condition.foldCondition((PrimitiveConstant) forX.asConstant(), (PrimitiveConstant) forY.asConstant(), unorderedIsTrue)); + } + return null; + } + /** * Does this operation represent an identity check such that for x == y, x is exactly the same * thing as y. This is generally true except for some floating point comparisons. @@ -221,7 +229,7 @@ public static LogicNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { LogicNode result = createCompareNode(condition, x, y, constantReflection); - return (result.graph() == null ? graph.unique(result) : result); + return (result.graph() == null ? graph.addOrUniqueWithInputs(result) : result); } public static LogicNode createCompareNode(Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { @@ -237,15 +245,15 @@ comparison = PointerEqualsNode.create(x, y); } else { assert x.getStackKind().isNumericInteger(); - comparison = IntegerEqualsNode.create(x, y, constantReflection); + comparison = IntegerEqualsNode.create(x, y); } } else if (condition == Condition.LT) { assert x.getStackKind().isNumericInteger(); - comparison = IntegerLessThanNode.create(x, y, constantReflection); + comparison = IntegerLessThanNode.create(x, y); } else { assert condition == Condition.BT; assert x.getStackKind().isNumericInteger(); - comparison = IntegerBelowNode.create(x, y, constantReflection); + comparison = IntegerBelowNode.create(x, y); } return comparison;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -83,6 +83,10 @@ if (synonym != null) { return synonym; } + ValueNode result = canonicalizeConditional(condition, trueValue, falseValue, trueValue.stamp().meet(falseValue.stamp())); + if (result != null) { + return result; + } return new ConditionalNode(condition, trueValue, falseValue); }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/DivNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/DivNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -58,9 +58,8 @@ ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); if (tryConstantFold != null) { return tryConstantFold; - } else { - return new DivNode(x, y); } + return canonical(null, op, x, y); } @Override @@ -70,9 +69,13 @@ return ret; } + return canonical(this, getOp(forX, forY), forX, forY); + } + + private static ValueNode canonical(DivNode self, BinaryOp<Div> op, ValueNode forX, ValueNode forY) { if (forY.isConstant()) { Constant c = forY.asConstant(); - if (getOp(forX, forY).isNeutral(c)) { + if (op.isNeutral(c)) { return forX; } if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) { @@ -88,14 +91,14 @@ } if (divResult != null) { if (signFlip) { - return new NegateNode(divResult); + return NegateNode.create(divResult); } else { return divResult; } } } } - return this; + return self != null ? self : new DivNode(forX, forY); } @Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -37,7 +37,6 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.util.GraphUtil; -import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.TriState; @NodeInfo(shortName = "==", cycles = NodeCycles.CYCLES_3) @@ -50,8 +49,8 @@ assert x.stamp().isCompatible(y.stamp()); } - public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { - LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, constantReflection, false); + public static LogicNode create(ValueNode x, ValueNode y) { + LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.EQ, x, y, false); if (result != null) { return result; } else {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -36,7 +36,6 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.util.GraphUtil; -import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.TriState; @NodeInfo(shortName = "<", cycles = NodeCycles.CYCLES_3) @@ -49,8 +48,8 @@ assert x.stamp().isCompatible(y.stamp()); } - public static LogicNode create(ValueNode x, ValueNode y, boolean unorderedIsTrue, ConstantReflectionProvider constantReflection) { - LogicNode result = CompareNode.tryConstantFold(Condition.LT, x, y, constantReflection, unorderedIsTrue); + public static LogicNode create(ValueNode x, ValueNode y, boolean unorderedIsTrue) { + LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.LT, x, y, unorderedIsTrue); if (result != null) { return result; } else {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -32,7 +32,6 @@ import org.graalvm.compiler.nodes.ValueNode; import jdk.vm.ci.code.CodeUtil; -import jdk.vm.ci.meta.ConstantReflectionProvider; @NodeInfo(shortName = "|<|") public final class IntegerBelowNode extends IntegerLowerThanNode { @@ -45,8 +44,8 @@ assert y.stamp() instanceof IntegerStamp; } - public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { - return OP.create(x, y, constantReflection); + public static LogicNode create(ValueNode x, ValueNode y) { + return OP.create(x, y); } @Override @@ -108,7 +107,7 @@ } @Override - protected IntegerLowerThanNode create(ValueNode x, ValueNode y) { + protected IntegerLowerThanNode createNode(ValueNode x, ValueNode y) { return new IntegerBelowNode(x, y); } }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -40,7 +40,6 @@ import org.graalvm.compiler.nodes.util.GraphUtil; import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.PrimitiveConstant; import jdk.vm.ci.meta.TriState; @@ -55,8 +54,8 @@ assert !y.getStackKind().isNumericFloat() && y.getStackKind() != JavaKind.Object; } - public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { - LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, constantReflection, false); + public static LogicNode create(ValueNode x, ValueNode y) { + LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.EQ, x, y, false); if (result != null) { return result; } else { @@ -117,6 +116,29 @@ } else if (forX.stamp().alwaysDistinct(forY.stamp())) { return LogicConstantNode.contradiction(); } + if (forX instanceof AddNode && forY instanceof AddNode) { + AddNode addX = (AddNode) forX; + AddNode addY = (AddNode) forY; + ValueNode v1 = null; + ValueNode v2 = null; + if (addX.getX() == addY.getX()) { + v1 = addX.getY(); + v2 = addY.getY(); + } else if (addX.getX() == addY.getY()) { + v1 = addX.getY(); + v2 = addY.getX(); + } else if (addX.getY() == addY.getX()) { + v1 = addX.getX(); + v2 = addY.getY(); + } else if (addX.getY() == addY.getY()) { + v1 = addX.getX(); + v2 = addY.getX(); + } + if (v1 != null) { + assert v2 != null; + return create(v1, v2); + } + } return super.canonical(tool, forX, forY); } @@ -130,14 +152,14 @@ // nonConstant can only be 0 or 1 (respective -1), test against 0 instead of 1 // (respective -1) for a more canonical graph and also to allow for faster execution // on specific platforms. - return LogicNegationNode.create(IntegerEqualsNode.create(nonConstant, ConstantNode.forIntegerKind(nonConstant.getStackKind(), 0), null)); + return LogicNegationNode.create(IntegerEqualsNode.create(nonConstant, ConstantNode.forIntegerKind(nonConstant.getStackKind(), 0))); } else if (primitiveConstant.asLong() == 0) { if (nonConstant instanceof AndNode) { AndNode andNode = (AndNode) nonConstant; return new IntegerTestNode(andNode.getX(), andNode.getY()); } else if (nonConstant instanceof SubNode) { SubNode subNode = (SubNode) nonConstant; - return IntegerEqualsNode.create(subNode.getX(), subNode.getY(), tool.getConstantReflection()); + return IntegerEqualsNode.create(subNode.getX(), subNode.getY()); } else if (nonConstant instanceof ShiftNode && nonConstant.stamp() instanceof IntegerStamp) { if (nonConstant instanceof LeftShiftNode) { LeftShiftNode shift = (LeftShiftNode) nonConstant;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java Thu Apr 06 22:13:13 2017 +0000 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java Thu Apr 06 23:01:27 2017 +0000 @@ -31,15 +31,14 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.LogicNegationNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.ValueNode; import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.PrimitiveConstant; @@ -55,8 +54,8 @@ assert !y.getStackKind().isNumericFloat() && y.getStackKind() != JavaKind.Object; } - public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { - return OP.create(x, y, constantReflection); + public static LogicNode create(ValueNode x, ValueNode y) { + return OP.create(x, y); } @Override @@ -91,79 +90,6 @@ } @Override - public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - ValueNode result = super.canonical(tool, forX, forY); - if (result != this) { - return result; - } - if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { - if (IntegerStamp.sameSign((IntegerStamp) forX.stamp(), (IntegerStamp) forY.stamp())) { - return new IntegerBelowNode(forX, forY); - } - } - if (forY.isConstant() && forY.asConstant().isDefaultForKind() && forX instanceof SubNode) { - // (x - y) < 0 when x - y is known not to underflow <=> x < y - SubNode sub = (SubNode) forX; - IntegerStamp xStamp = (IntegerStamp) sub.getX().stamp(); - IntegerStamp yStamp = (IntegerStamp) sub.getY().stamp(); - long minValue = CodeUtil.minValue(xStamp.getBits()); - long maxValue = CodeUtil.maxValue(xStamp.getBits()); - - if (!subtractMayUnderflow(xStamp.lowerBound(), yStamp.upperBound(), minValue) && !subtractMayOverflow(xStamp.upperBound(), yStamp.lowerBound(), maxValue)) { - return new IntegerLessThanNode(sub.getX(), sub.getY()); - } - } - - int bits = ((IntegerStamp) getX().stamp()).getBits(); - assert ((IntegerStamp) getY().stamp()).getBits() == bits; - long min = OP.minValue(bits); - long xResidue = 0; - ValueNode left = null; - JavaConstant leftCst = null; - if (forX instanceof AddNode) { - AddNode xAdd = (AddNode) forX; - if (xAdd.getY().isJavaConstant()) { - long xCst = xAdd.getY().asJavaConstant().asLong(); - xResidue = xCst - min; - left = xAdd.getX(); - } - } else if (forX.isJavaConstant()) { - leftCst = forX.asJavaConstant(); - } - if (left != null || leftCst != null) { - long yResidue = 0; - ValueNode right = null; - JavaConstant rightCst = null; - if (forY instanceof AddNode) { - AddNode yAdd = (AddNode) forY; - if (yAdd.getY().isJavaConstant()) { - long yCst = yAdd.getY().asJavaConstant().asLong(); - yResidue = yCst - min; - right = yAdd.getX(); - } - } else if (forY.isJavaConstant()) { - rightCst = forY.asJavaConstant(); - } - if (right != null || rightCst != null) { - if ((xResidue == 0 && left != null) || (yResidue == 0 && right != null)) { - if (left == null) { - left = ConstantNode.forIntegerBits(bits, leftCst.asLong() - min); - } else if (xResidue != 0) { - left = AddNode.create(left, ConstantNode.forIntegerBits(bits, xResidue)); - } - if (right == null) { - right = ConstantNode.forIntegerBits(bits, rightCst.asLong() - min); - } else if (yResidue != 0) { - right = AddNode.create(right, ConstantNode.forIntegerBits(bits, yResidue)); - } - return new IntegerBelowNode(left, right); - } - } - } - return this; - } - - @Override protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) { return new FloatLessThanNode(newX, newY, true); @@ -176,12 +102,104 @@ public static class LessThanOp extends LowerOp { @Override + protected LogicNode findSynonym(ValueNode forX, ValueNode forY) { + LogicNode result = super.findSynonym(forX, forY); + if (result != null) { + return result; + } + if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { + if (IntegerStamp.sameSign((IntegerStamp) forX.stamp(), (IntegerStamp) forY.stamp())) { + return new IntegerBelowNode(forX, forY); + } + } + if (forY.isConstant() && forX instanceof SubNode) { + SubNode sub = (SubNode) forX; + ValueNode xx = null; + ValueNode yy = null; + boolean negate = false; + if (forY.asConstant().isDefaultForKind()) { + // (x - y) < 0 when x - y is known not to underflow <=> x < y + xx = sub.getX(); + yy = sub.getY(); + } else if (forY.isJavaConstant() && forY.asJavaConstant().asLong() == 1) { + // (x - y) < 1 when x - y is known not to underflow <=> !(y < x) + xx = sub.getY(); + yy = sub.getX(); + negate = true; + } + if (xx != null) { + assert yy != null; + IntegerStamp xStamp = (IntegerStamp) sub.getX().stamp(); + IntegerStamp yStamp = (IntegerStamp) sub.getY().stamp(); + long minValue = CodeUtil.minValue(xStamp.getBits()); + long maxValue = CodeUtil.maxValue(xStamp.getBits()); + + if (!subtractMayUnderflow(xStamp.lowerBound(), yStamp.upperBound(), minValue) && !subtractMayOverflow(xStamp.upperBound(), yStamp.lowerBound(), maxValue)) { + LogicNode logic = new IntegerLessThanNode(xx, yy); + if (negate) { + logic = LogicNegationNode.create(logic); + } + return logic; + } + } + } + + int bits = ((IntegerStamp) forX.stamp()).getBits(); + assert ((IntegerStamp) forY.stamp()).getBits() == bits; + long min = OP.minValue(bits);