# HG changeset patch # User Christian Humer # Date 1367009045 -7200 # Node ID f43d043888154c76ee6487c566cb88be463aa651 # Parent 52fde777a605e0784c128d5d0697c6212b704e67# Parent 52e6d0e8d6f7da8610607032c7677c1bd94a1b48 Merge. diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Fri Apr 26 22:44:05 2013 +0200 @@ -22,15 +22,11 @@ */ package com.oracle.graal.compiler.test; -import java.util.*; - import org.junit.*; import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.Lowerable.*; import com.oracle.graal.phases.common.*; @@ -96,36 +92,10 @@ Debug.dump(graph, "After lowering"); - ArrayList merges = new ArrayList<>(); - ArrayList reads = new ArrayList<>(); - for (Node n : graph.getNodes()) { - if (n instanceof MergeNode) { - // check shape - MergeNode merge = (MergeNode) n; - - if (merge.inputs().count() == 2) { - for (EndNode m : merge.forwardEnds()) { - if (m.predecessor() != null && m.predecessor() instanceof BeginNode && m.predecessor().predecessor() instanceof IfNode) { - IfNode o = (IfNode) m.predecessor().predecessor(); - if (o.falseSuccessor().next() instanceof DeoptimizeNode) { - merges.add(merge); - } - } - } - } - } - if (n instanceof IntegerAddNode) { - IntegerAddNode ian = (IntegerAddNode) n; - - Assert.assertTrue(ian.y() instanceof ConstantNode); - Assert.assertTrue(ian.x() instanceof FloatingReadNode); - reads.add((FloatingReadNode) ian.x()); - } - } - - Assert.assertTrue(merges.size() >= reads.size()); - for (int i = 0; i < reads.size(); i++) { - assertOrderedAfterSchedule(graph, merges.get(i), reads.get(i)); + for (FloatingReadNode node : graph.getNodes(LocalNode.class).first().usages().filter(FloatingReadNode.class)) { + // Checking that the parameter a is not directly used for the access to field + // x10 (because x10 must be guarded by the checkcast). + Assert.assertTrue(node.location().locationIdentity() == LocationNode.FINAL_LOCATION); } } }); diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Fri Apr 26 22:44:05 2013 +0200 @@ -34,16 +34,10 @@ public HighTier() { if (GraalOptions.FullUnroll) { addPhase(new LoopFullUnrollPhase()); - if (GraalOptions.OptCanonicalizer) { - addPhase(new CanonicalizerPhase()); - } } if (GraalOptions.OptTailDuplication) { addPhase(new TailDuplicationPhase()); - if (GraalOptions.OptCanonicalizer) { - addPhase(new CanonicalizerPhase()); - } } if (GraalOptions.PartialEscapeAnalysis) { diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Fri Apr 26 22:44:05 2013 +0200 @@ -47,7 +47,8 @@ private int deletedNodeCount; private GraphEventLog eventLog; - InputChangedListener inputChanged; + NodeChangedListener inputChanged; + NodeChangedListener usagesDroppedZero; private final HashMap cachedNodes = new HashMap<>(); private static final class CacheEntry { @@ -152,12 +153,12 @@ return node; } - public interface InputChangedListener { + public interface NodeChangedListener { - void inputChanged(Node node); + void nodeChanged(Node node); } - public void trackInputChange(InputChangedListener inputChangedListener) { + public void trackInputChange(NodeChangedListener inputChangedListener) { this.inputChanged = inputChangedListener; } @@ -165,6 +166,14 @@ inputChanged = null; } + public void trackUsagesDroppedZero(NodeChangedListener usagesDroppedZeroListener) { + this.usagesDroppedZero = usagesDroppedZeroListener; + } + + public void stopTrackingUsagesDroppedZero() { + usagesDroppedZero = null; + } + /** * Adds a new node to the graph, if a similar node already exists in the graph, the * provided node will not be added to the graph but the similar node will be returned diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Apr 26 22:44:05 2013 +0200 @@ -25,7 +25,7 @@ import java.lang.annotation.*; import java.util.*; -import com.oracle.graal.graph.Graph.InputChangedListener; +import com.oracle.graal.graph.Graph.NodeChangedListener; import com.oracle.graal.graph.NodeClass.*; import com.oracle.graal.graph.iterators.*; @@ -193,12 +193,17 @@ assert assertTrue(result, "not found in usages, old input: %s", oldInput); } if (newInput != null) { - InputChangedListener inputChanged = graph.inputChanged; + NodeChangedListener inputChanged = graph.inputChanged; if (inputChanged != null) { - inputChanged.inputChanged(this); + inputChanged.nodeChanged(this); } assert newInput.usages != null : "not yet added? " + newInput; newInput.usages.add(this); + } else if (oldInput != null && oldInput.usages().isEmpty()) { + NodeChangedListener nodeChangedListener = graph.usagesDroppedZero; + if (nodeChangedListener != null) { + nodeChangedListener.nodeChanged(oldInput); + } } } } @@ -253,9 +258,9 @@ boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); assert assertTrue(result, "not found in inputs, usage: %s", usage); if (other != null) { - InputChangedListener inputChanged = graph.inputChanged; + NodeChangedListener inputChanged = graph.inputChanged; if (inputChanged != null) { - inputChanged.inputChanged(usage); + inputChanged.nodeChanged(usage); } other.usages.add(usage); } @@ -299,6 +304,12 @@ for (Node input : inputs()) { removeThisFromUsages(input); + if (input.usages().isEmpty()) { + NodeChangedListener nodeChangedListener = graph.usagesDroppedZero; + if (nodeChangedListener != null) { + nodeChangedListener.nodeChanged(input); + } + } } getNodeClass().clearInputs(this); } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Apr 26 22:44:05 2013 +0200 @@ -27,6 +27,7 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.hotspot.amd64.AMD64HotSpotUnwindOp.*; +import java.lang.reflect.*; import java.util.*; import com.oracle.graal.amd64.*; @@ -234,6 +235,7 @@ } else { assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special; HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target(); + assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method."; Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant(); append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod)); } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Fri Apr 26 22:44:05 2013 +0200 @@ -84,8 +84,8 @@ long nonVectorBytes = byteLength % VECTOR_SIZE; long srcOffset = (long) srcPos * elementSize; long destOffset = (long) destPos * elementSize; - if (src == dest && srcPos < destPos) { // bad aliased case - probability(NOT_FREQUENT_PROBABILITY); + if (probability(NOT_FREQUENT_PROBABILITY, src == dest) && probability(NOT_FREQUENT_PROBABILITY, srcPos < destPos)) { + // bad aliased case for (long i = byteLength - elementSize; i >= byteLength - nonVectorBytes; i -= elementSize) { UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind); } @@ -107,7 +107,6 @@ public static void checkNonNull(Object obj) { if (obj == null) { - probability(DEOPT_PATH_PROBABILITY); checkNPECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } @@ -116,7 +115,6 @@ public static int checkArrayType(Word hub) { int layoutHelper = readLayoutHelper(hub); if (layoutHelper >= 0) { - probability(DEOPT_PATH_PROBABILITY); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } return layoutHelper; @@ -124,27 +122,22 @@ public static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length) { if (srcPos < 0) { - probability(DEOPT_PATH_PROBABILITY); checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (destPos < 0) { - probability(DEOPT_PATH_PROBABILITY); checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (length < 0) { - probability(DEOPT_PATH_PROBABILITY); checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (srcPos + length > ArrayLengthNode.arrayLength(src)) { - probability(DEOPT_PATH_PROBABILITY); checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (destPos + length > ArrayLengthNode.arrayLength(dest)) { - probability(DEOPT_PATH_PROBABILITY); checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } @@ -278,13 +271,10 @@ int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) == 0); - if (srcHub.equal(destHub) && src != dest) { - probability(FAST_PATH_PROBABILITY); - + if (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, src != dest)) { checkLimits(src, srcPos, dest, destPos, length); - if (isObjectArray) { + if (probability(FAST_PATH_PROBABILITY, isObjectArray)) { genericObjectExactCallCounter.inc(); - probability(FAST_PATH_PROBABILITY); arrayObjectCopy(src, srcPos, dest, destPos, length); } else { genericPrimitiveCallCounter.inc(); diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java Fri Apr 26 22:44:05 2013 +0200 @@ -65,13 +65,11 @@ */ @Snippet public static Object checkcastExact(Object object, Word exactHub, @ConstantParameter boolean checkNull) { - if (checkNull && object == null) { - probability(NOT_FREQUENT_PROBABILITY); + if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) { isNull.inc(); } else { Word objectHub = loadHub(object); if (objectHub.notEqual(exactHub)) { - probability(DEOPT_PATH_PROBABILITY); exactMiss.inc(); DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); } @@ -92,13 +90,11 @@ */ @Snippet public static Object checkcastPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, @ConstantParameter boolean checkNull) { - if (checkNull && object == null) { - probability(NOT_FREQUENT_PROBABILITY); + if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) { isNull.inc(); } else { Word objectHub = loadHub(object); if (objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub)) { - probability(DEOPT_PATH_PROBABILITY); displayMiss.inc(); DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); } @@ -113,8 +109,7 @@ */ @Snippet public static Object checkcastSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @ConstantParameter boolean checkNull) { - if (checkNull && object == null) { - probability(NOT_FREQUENT_PROBABILITY); + if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) { isNull.inc(); } else { Word objectHub = loadHub(object); @@ -142,8 +137,7 @@ */ @Snippet public static Object checkcastDynamic(Word hub, Object object, @ConstantParameter boolean checkNull) { - if (checkNull && object == null) { - probability(NOT_FREQUENT_PROBABILITY); + if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) { isNull.inc(); } else { Word objectHub = loadHub(object); diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSnippetUtils.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSnippetUtils.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSnippetUtils.java Fri Apr 26 22:44:05 2013 +0200 @@ -608,11 +608,9 @@ // this code is independent from biased locking (although it does not look that way) final Word biasedLock = mark.and(biasedLockMaskInPlace()); - if (biasedLock.equal(Word.unsigned(unlockedMask()))) { - probability(FAST_PATH_PROBABILITY); + if (probability(FAST_PATH_PROBABILITY, biasedLock.equal(Word.unsigned(unlockedMask())))) { int hash = (int) mark.unsignedShiftRight(identityHashCodeShift()).rawValue(); - if (hash != uninitializedIdentityHashCodeValue()) { - probability(FAST_PATH_PROBABILITY); + if (probability(FAST_PATH_PROBABILITY, hash != uninitializedIdentityHashCodeValue())) { return hash; } } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Fri Apr 26 22:44:05 2013 +0200 @@ -58,14 +58,12 @@ */ @Snippet public static Object instanceofExact(Object object, Word exactHub, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { - if (checkNull && object == null) { - probability(NOT_FREQUENT_PROBABILITY); + if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) { isNull.inc(); return falseValue; } Word objectHub = loadHub(object); - if (objectHub.notEqual(exactHub)) { - probability(LIKELY_PROBABILITY); + if (probability(LIKELY_PROBABILITY, objectHub.notEqual(exactHub))) { exactMiss.inc(); return falseValue; } @@ -78,14 +76,12 @@ */ @Snippet public static Object instanceofPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { - if (checkNull && object == null) { - probability(NOT_FREQUENT_PROBABILITY); + if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) { isNull.inc(); return falseValue; } Word objectHub = loadHub(object); - if (objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub)) { - probability(NOT_LIKELY_PROBABILITY); + if (probability(NOT_LIKELY_PROBABILITY, objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub))) { displayMiss.inc(); return falseValue; } @@ -99,8 +95,7 @@ @Snippet public static Object instanceofSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { - if (checkNull && object == null) { - probability(NOT_FREQUENT_PROBABILITY); + if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) { isNull.inc(); return falseValue; } @@ -110,8 +105,7 @@ for (int i = 0; i < hints.length; i++) { Word hintHub = hints[i]; boolean positive = hintIsPositive[i]; - if (hintHub.equal(objectHub)) { - probability(NOT_FREQUENT_PROBABILITY); + if (probability(NOT_FREQUENT_PROBABILITY, hintHub.equal(objectHub))) { hintsHit.inc(); return positive ? trueValue : falseValue; } @@ -127,8 +121,7 @@ */ @Snippet public static Object instanceofDynamic(Class mirror, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { - if (checkNull && object == null) { - probability(NOT_FREQUENT_PROBABILITY); + if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) { isNull.inc(); return falseValue; } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Fri Apr 26 22:44:05 2013 +0200 @@ -102,10 +102,9 @@ final Word biasableLockBits = mark.and(biasedLockMaskInPlace()); // First check to see whether biasing is enabled for this object - if (biasableLockBits.notEqual(Word.unsigned(biasedLockPattern()))) { + if (probability(NOT_FREQUENT_PROBABILITY, biasableLockBits.notEqual(Word.unsigned(biasedLockPattern())))) { // Biasing not enabled -> fall through to lightweight locking } else { - probability(FREQUENT_PROBABILITY); // The bias pattern is present in the object's mark word. Need to check // whether the bias owner and the epoch are both still current. Word hub = loadHub(object); @@ -115,9 +114,8 @@ trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord); trace(trace, " thread: 0x%016lx\n", thread); trace(trace, " tmp: 0x%016lx\n", tmp); - if (tmp.equal(0)) { + if (probability(FREQUENT_PROBABILITY, tmp.equal(0))) { // Object is already biased to current thread -> done - probability(FREQUENT_PROBABILITY); traceObject(trace, "+lock{bias:existing}", object); return; } @@ -131,8 +129,7 @@ // If the low three bits in the xor result aren't clear, that means // the prototype header is no longer biasable and we have to revoke // the bias on this object. - if (tmp.and(biasedLockMaskInPlace()).equal(0)) { - probability(FREQUENT_PROBABILITY); + if (probability(FREQUENT_PROBABILITY, tmp.and(biasedLockMaskInPlace()).equal(0))) { // Biasing is still enabled for object's type. See whether the // epoch of the current bias is still valid, meaning that the epoch // bits of the mark word are equal to the epoch bits of the @@ -142,8 +139,7 @@ // that the current epoch is invalid in order to do this because // otherwise the manipulations it performs on the mark word are // illegal. - if (tmp.and(epochMaskInPlace()).equal(0)) { - probability(FREQUENT_PROBABILITY); + if (probability(FREQUENT_PROBABILITY, tmp.and(epochMaskInPlace()).equal(0))) { // The epoch of the current bias is still valid but we know nothing // about the owner; it might be set or it might be clear. Try to // acquire the bias of the object using an atomic operation. If this @@ -154,7 +150,7 @@ Word biasedMark = unbiasedMark.or(thread); trace(trace, " unbiasedMark: 0x%016lx\n", unbiasedMark); trace(trace, " biasedMark: 0x%016lx\n", biasedMark); - if (compareAndSwap(object, markOffset(), unbiasedMark, biasedMark, MARK_WORD_LOCATION).equal(unbiasedMark)) { + if (probability(VERY_FAST_DEOPT_PATH_PROBABILITY, compareAndSwap(object, markOffset(), unbiasedMark, biasedMark, MARK_WORD_LOCATION).equal(unbiasedMark))) { // Object is now biased to current thread -> done traceObject(trace, "+lock{bias:acquired}", object); return; @@ -162,7 +158,6 @@ // If the biasing toward our thread failed, this means that another thread // owns the bias and we need to revoke that bias. The revocation will occur // in the interpreter runtime. - probability(DEOPT_PATH_PROBABILITY); traceObject(trace, "+lock{stub:revoke}", object); MonitorEnterStubCall.call(object, lock); return; @@ -175,7 +170,7 @@ // the bias from one thread to another directly in this situation. Word biasedMark = prototypeMarkWord.or(thread); trace(trace, " biasedMark: 0x%016lx\n", biasedMark); - if (compareAndSwap(object, markOffset(), mark, biasedMark, MARK_WORD_LOCATION).equal(mark)) { + if (probability(VERY_FAST_DEOPT_PATH_PROBABILITY, compareAndSwap(object, markOffset(), mark, biasedMark, MARK_WORD_LOCATION).equal(mark))) { // Object is now biased to current thread -> done traceObject(trace, "+lock{bias:transfer}", object); return; @@ -183,7 +178,6 @@ // If the biasing toward our thread failed, then another thread // succeeded in biasing it toward itself and we need to revoke that // bias. The revocation will occur in the runtime in the slow case. - probability(DEOPT_PATH_PROBABILITY); traceObject(trace, "+lock{stub:epoch-expired}", object); MonitorEnterStubCall.call(object, lock); return; @@ -239,9 +233,8 @@ // significant 2 bits cleared and page_size is a power of 2 final Word alignedMask = Word.unsigned(wordSize() - 1); final Word stackPointer = stackPointer(); - if (currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0)) { + if (probability(VERY_SLOW_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0))) { // Most likely not a recursive lock, go into a slow runtime call - probability(DEOPT_PATH_PROBABILITY); traceObject(trace, "+lock{stub:failed-cas}", object); MonitorEnterStubCall.call(object, lock); return; @@ -290,8 +283,7 @@ // the bias bit would be clear. final Word mark = loadWordFromObject(object, markOffset()); trace(trace, " mark: 0x%016lx\n", mark); - if (mark.and(biasedLockMaskInPlace()).equal(Word.unsigned(biasedLockPattern()))) { - probability(FREQUENT_PROBABILITY); + if (probability(FREQUENT_PROBABILITY, mark.and(biasedLockMaskInPlace()).equal(Word.unsigned(biasedLockPattern())))) { endLockScope(); decCounter(); traceObject(trace, "-lock{bias}", object); @@ -313,10 +305,9 @@ // Test if object's mark word is pointing to the displaced mark word, and if so, restore // the displaced mark in the object - if the object's mark word is not pointing to // the displaced mark word, do unlocking via runtime call. - if (DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark, MARK_WORD_LOCATION).notEqual(lock)) { + if (probability(VERY_SLOW_PATH_PROBABILITY, DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark, MARK_WORD_LOCATION).notEqual(lock))) { // The object's mark word was not pointing to the displaced header, // we do unlocking via runtime call. - probability(DEOPT_PATH_PROBABILITY); traceObject(trace, "-lock{stub}", object); MonitorExitStubCall.call(object); } else { diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri Apr 26 22:44:05 2013 +0200 @@ -64,8 +64,7 @@ * this check might lead to problems if the TLAB is within 16GB of the address space end * (checked in c++ code) */ - if (newTop.belowOrEqual(end)) { - probability(FAST_PATH_PROBABILITY); + if (probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { writeTlabTop(thread, newTop); return top; } @@ -76,11 +75,10 @@ public static Object initializeObject(Word memory, Word hub, Word prototypeMarkWord, @ConstantParameter int size, @ConstantParameter boolean fillContents, @ConstantParameter boolean locked) { Object result; - if (memory.equal(0)) { + if (probability(SLOW_PATH_PROBABILITY, memory.equal(0))) { new_stub.inc(); result = NewInstanceStubCall.call(hub); } else { - probability(FAST_PATH_PROBABILITY); if (locked) { formatObject(hub, size, memory, thread().or(biasedLockPattern()), fillContents); } else { @@ -108,11 +106,10 @@ private static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, int headerSize, boolean fillContents) { Object result; - if (memory.equal(0)) { + if (probability(SLOW_PATH_PROBABILITY, memory.equal(0))) { newarray_stub.inc(); result = NewArrayStubCall.call(hub, length); } else { - probability(FAST_PATH_PROBABILITY); newarray_loopInit.inc(); formatArray(hub, allocationSize, length, headerSize, memory, prototypeMarkWord, fillContents); result = memory.toObject(); @@ -130,7 +127,6 @@ public static Object allocateArrayAndInitialize(int length, @ConstantParameter int alignment, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, @ConstantParameter boolean fillContents, @ConstantParameter ResolvedJavaType type) { if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { - probability(DEOPT_PATH_PROBABILITY); // This handles both negative array sizes and very large array sizes DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Fri Apr 26 22:44:05 2013 +0200 @@ -84,7 +84,6 @@ private static Word getAndCheckHub(Object src) { Word hub = loadHub(src); if (!(src instanceof Cloneable)) { - probability(DEOPT_PATH_PROBABILITY); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } return hub; @@ -110,8 +109,7 @@ genericCloneCounter.inc(); Word hub = getAndCheckHub(src); int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION); - if (layoutHelper < 0) { - probability(LIKELY_PROBABILITY); + if (probability(LIKELY_PROBABILITY, layoutHelper < 0)) { genericArrayCloneCounter.inc(); return arrayClone(src, hub, layoutHelper); } else { diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java Fri Apr 26 22:44:05 2013 +0200 @@ -56,8 +56,7 @@ @MethodSubstitution public static int identityHashCode(Object x) { - if (x == null) { - probability(NOT_FREQUENT_PROBABILITY); + if (probability(NOT_FREQUENT_PROBABILITY, x == null)) { return 0; } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java Fri Apr 26 22:44:05 2013 +0200 @@ -89,8 +89,7 @@ Word secondarySupers = s.readWord(secondarySupersOffset(), SECONDARY_SUPERS_LOCATION); int length = secondarySupers.readInt(metaspaceArrayLengthOffset(), FINAL_LOCATION); for (int i = 0; i < length; i++) { - if (t.equal(loadSecondarySupersElement(secondarySupers, i))) { - probability(NOT_LIKELY_PROBABILITY); + if (probability(NOT_LIKELY_PROBABILITY, t.equal(loadSecondarySupersElement(secondarySupers, i)))) { s.writeWord(secondarySuperCacheOffset(), t, SECONDARY_SUPER_CACHE_LOCATION); secondariesHit.inc(); return true; diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Apr 26 22:44:05 2013 +0200 @@ -34,7 +34,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.api.meta.ResolvedJavaType.Representation; import com.oracle.graal.bytecode.*; @@ -798,12 +797,7 @@ if (!optimisticOpts.useTypeCheckHints() || !canHaveSubtype(type)) { return null; } else { - ResolvedJavaType uniqueSubtype = type.findUniqueConcreteSubtype(); - if (uniqueSubtype != null) { - return new JavaTypeProfile(profilingInfo.getNullSeen(bci()), 0.0D, new ProfiledType(uniqueSubtype, 1.0D)); - } else { - return profilingInfo.getTypeProfile(bci()); - } + return profilingInfo.getTypeProfile(bci()); } } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Reflection_getCallerClass01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Reflection_getCallerClass01.java Fri Apr 26 22:43:37 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2007, 2012, 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 com.oracle.graal.jtt.reflect; - -import com.oracle.graal.jtt.*; -import org.junit.*; - -import sun.reflect.*; - -/* - */ -public final class Reflection_getCallerClass01 extends JTTTest { - - public static final class Caller1 { - - private Caller1() { - } - - static String caller1(int depth) { - return Reflection.getCallerClass(depth).getName(); - } - } - - public static final class Caller2 { - - private Caller2() { - } - - static String caller2(int depth) { - return Caller1.caller1(depth); - } - } - - public static String test(int depth) { - return Caller2.caller2(depth); - } - - @Test - public void run0() throws Throwable { - runTest("test", 0); - } - - @Test - public void run1() throws Throwable { - runTest("test", 1); - } - - @Test - public void run2() throws Throwable { - runTest("test", 2); - } - -} diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Fri Apr 26 22:44:05 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.java; +import java.lang.reflect.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -102,6 +104,14 @@ for (Node n : usages()) { assertTrue(n instanceof Invoke, "call target can only be used from an invoke (%s)", n); } + if (invokeKind == InvokeKind.Special || invokeKind == InvokeKind.Static) { + assertFalse(Modifier.isAbstract(targetMethod.getModifiers()), "special calls or static calls are only allowed for concrete methods (%s)", targetMethod); + } + if (invokeKind == InvokeKind.Static) { + assertTrue(Modifier.isStatic(targetMethod.getModifiers()), "static calls are only allowed for static methods (%s)", targetMethod); + } else { + assertFalse(Modifier.isStatic(targetMethod.getModifiers()), "static calls are only allowed for non-static methods (%s)", targetMethod); + } return super.verify(); } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Fri Apr 26 22:44:05 2013 +0200 @@ -22,14 +22,13 @@ */ package com.oracle.graal.phases.common; -import java.util.*; import java.util.concurrent.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Graph.InputChangedListener; +import com.oracle.graal.graph.Graph.NodeChangedListener; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -49,6 +48,7 @@ public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits"); private final CustomCanonicalizer customCanonicalizer; + private final Iterable workingSet; public interface CustomCanonicalizer { @@ -60,12 +60,17 @@ } public CanonicalizerPhase(CustomCanonicalizer customCanonicalizer) { + this(customCanonicalizer, null); + } + + public CanonicalizerPhase(CustomCanonicalizer customCanonicalizer, Iterable workingSet) { this.customCanonicalizer = customCanonicalizer; + this.workingSet = workingSet; } @Override protected void run(StructuredGraph graph, PhaseContext context) { - new Instance(context.getRuntime(), context.getAssumptions(), null, customCanonicalizer).run(graph); + new Instance(context.getRuntime(), context.getAssumptions(), workingSet, customCanonicalizer).run(graph); } public static class Instance extends Phase { @@ -78,7 +83,6 @@ private NodeWorkList workList; private Tool tool; - private List snapshotTemp; public Instance(MetaAccessProvider runtime, Assumptions assumptions) { this(runtime, assumptions, null, 0, null); @@ -110,7 +114,6 @@ this.runtime = runtime; this.customCanonicalizer = customCanonicalizer; this.initWorkingSet = workingSet; - this.snapshotTemp = new ArrayList<>(); } @Override @@ -129,19 +132,22 @@ } private void processWorkSet(StructuredGraph graph) { - graph.trackInputChange(new InputChangedListener() { + NodeChangedListener nodeChangedListener = new NodeChangedListener() { @Override - public void inputChanged(Node node) { + public void nodeChanged(Node node) { workList.addAgain(node); } - }); + }; + graph.trackInputChange(nodeChangedListener); + graph.trackUsagesDroppedZero(nodeChangedListener); for (Node n : workList) { processNode(n, graph); } graph.stopTrackingInputChange(); + graph.stopTrackingUsagesDroppedZero(); } private void processNode(Node node, StructuredGraph graph) { @@ -153,17 +159,9 @@ } int mark = graph.getMark(); if (!tryKillUnused(node)) { - node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp); if (!tryCanonicalize(node, graph)) { tryInferStamp(node, graph); - } else { - for (Node in : snapshotTemp) { - if (in.isAlive() && in.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(in); - } - } } - snapshotTemp.clear(); } for (Node newNode : graph.getNewNodes(mark)) { diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Fri Apr 26 22:44:05 2013 +0200 @@ -42,6 +42,7 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; public class InliningUtil { @@ -254,6 +255,10 @@ Class macroNodeClass = getMacroNodeClass(replacements, concrete); StructuredGraph graph = (StructuredGraph) invoke.asNode().graph(); if (macroNodeClass != null) { + if (((MethodCallTargetNode) invoke.callTarget()).targetMethod() != concrete) { + assert ((MethodCallTargetNode) invoke.callTarget()).invokeKind() != InvokeKind.Static; + InliningUtil.replaceInvokeCallTarget(invoke, graph, InvokeKind.Special, concrete); + } FixedWithNextNode macroNode; try { macroNode = macroNodeClass.getConstructor(Invoke.class).newInstance(invoke); @@ -294,12 +299,12 @@ } }); } + } - protected void replaceInvokeCallTarget(StructuredGraph graph, InvokeKind invokeKind, ResolvedJavaMethod targetMethod) { - MethodCallTargetNode oldCallTarget = (MethodCallTargetNode) invoke.callTarget(); - MethodCallTargetNode newCallTarget = graph.add(new MethodCallTargetNode(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType())); - invoke.asNode().replaceFirstInput(oldCallTarget, newCallTarget); - } + public static void replaceInvokeCallTarget(Invoke invoke, StructuredGraph graph, InvokeKind invokeKind, ResolvedJavaMethod targetMethod) { + MethodCallTargetNode oldCallTarget = (MethodCallTargetNode) invoke.callTarget(); + MethodCallTargetNode newCallTarget = graph.add(new MethodCallTargetNode(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType())); + invoke.asNode().replaceFirstInput(oldCallTarget, newCallTarget); } /** @@ -378,7 +383,7 @@ @Override public void tryToDevirtualizeInvoke(StructuredGraph graph, MetaAccessProvider runtime, Assumptions assumptions) { createGuard(graph, runtime); - replaceInvokeCallTarget(graph, InvokeKind.Special, concrete); + replaceInvokeCallTarget(invoke, graph, InvokeKind.Special, concrete); } private void createGuard(StructuredGraph graph, MetaAccessProvider runtime) { @@ -446,7 +451,7 @@ if (hasSingleMethod()) { inlineSingleMethod(graph, callback, replacements, assumptions); } else { - inlineMultipleMethods(graph, callback, replacements, assumptions); + inlineMultipleMethods(graph, callback, replacements, assumptions, runtime); } } @@ -458,7 +463,7 @@ return notRecordedTypeProbability > 0; } - private void inlineMultipleMethods(StructuredGraph graph, InliningCallback callback, Replacements replacements, Assumptions assumptions) { + private void inlineMultipleMethods(StructuredGraph graph, InliningCallback callback, Replacements replacements, Assumptions assumptions, MetaAccessProvider runtime) { int numberOfMethods = concretes.size(); FixedNode continuation = invoke.next(); @@ -560,7 +565,7 @@ if (opportunities > 0) { metricInliningTailDuplication.increment(); Debug.log("MultiTypeGuardInlineInfo starting tail duplication (%d opportunities)", opportunities); - TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacementNodes); + TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacementNodes, new HighTierContext(runtime, assumptions, replacements)); } } } @@ -730,7 +735,7 @@ ValueNode receiver = ((MethodCallTargetNode) invoke.callTarget()).receiver(); PiNode anchoredReceiver = createAnchoredReceiver(graph, invocationEntry, target.getDeclaringClass(), receiver, false); invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver); - replaceInvokeCallTarget(graph, kind, target); + replaceInvokeCallTarget(invoke, graph, kind, target); } private static BeginNode createUnknownTypeSuccessor(StructuredGraph graph) { @@ -775,15 +780,13 @@ @Override public void inline(StructuredGraph graph, MetaAccessProvider runtime, Replacements replacements, InliningCallback callback, Assumptions assumptions) { assumptions.record(takenAssumption); - Debug.log("recording assumption: %s", takenAssumption); - super.inline(graph, runtime, replacements, callback, assumptions); } @Override public void tryToDevirtualizeInvoke(StructuredGraph graph, MetaAccessProvider runtime, Assumptions assumptions) { assumptions.record(takenAssumption); - replaceInvokeCallTarget(graph, InvokeKind.Special, concrete); + replaceInvokeCallTarget(invoke, graph, InvokeKind.Special, concrete); } @Override diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Fri Apr 26 22:44:05 2013 +0200 @@ -24,7 +24,7 @@ import java.util.*; -import com.oracle.graal.graph.Graph.InputChangedListener; +import com.oracle.graal.graph.Graph.NodeChangedListener; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; @@ -49,7 +49,7 @@ } } - private static class Listener implements InputChangedListener { + private static class Listener implements NodeChangedListener { private final Set canonicalizationRoots; @@ -58,7 +58,7 @@ } @Override - public void inputChanged(Node node) { + public void nodeChanged(Node node) { canonicalizationRoots.add(node); } } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Fri Apr 26 22:44:05 2013 +0200 @@ -36,13 +36,14 @@ import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.graph.*; +import com.oracle.graal.phases.tiers.*; /** * This class is a phase that looks for opportunities for tail duplication. The static method - * {@link #tailDuplicate(MergeNode, TailDuplicationDecision, List)} can also be used to drive tail - * duplication from other places, e.g., inlining. + * {@link #tailDuplicate(MergeNode, TailDuplicationDecision, List, PhaseContext)} can also be used + * to drive tail duplication from other places, e.g., inlining. */ -public class TailDuplicationPhase extends Phase { +public class TailDuplicationPhase extends BasePhase { /* * Various metrics on the circumstances in which tail duplication was/wasn't performed. @@ -129,14 +130,14 @@ }; @Override - protected void run(StructuredGraph graph) { + protected void run(StructuredGraph graph, PhaseContext phaseContext) { NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(graph).apply(); // A snapshot is taken here, so that new MergeNode instances aren't considered for tail // duplication. for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) { if (!(merge instanceof LoopBeginNode) && nodeProbabilities.get(merge) >= GraalOptions.TailDuplicationProbability) { - tailDuplicate(merge, DEFAULT_DECISION, null); + tailDuplicate(merge, DEFAULT_DECISION, null, phaseContext); } } } @@ -156,8 +157,9 @@ * size needs to match the merge's end count. Each entry can either be null or a * {@link PiNode}, and is used to replace {@link PiNode#object()} with the * {@link PiNode} in the duplicated branch that corresponds to the entry. + * @param phaseContext */ - public static boolean tailDuplicate(MergeNode merge, TailDuplicationDecision decision, List replacements) { + public static boolean tailDuplicate(MergeNode merge, TailDuplicationDecision decision, List replacements, PhaseContext phaseContext) { assert !(merge instanceof LoopBeginNode); assert replacements == null || replacements.size() == merge.forwardEndCount(); FixedNode fixed = merge; @@ -171,14 +173,14 @@ metricDuplicationEnd.increment(); if (decision.doTransform(merge, fixedCount)) { metricDuplicationEndPerformed.increment(); - new DuplicationOperation(merge, replacements).duplicate(); + new DuplicationOperation(merge, replacements).duplicate(phaseContext); return true; } } else if (merge.stateAfter() != null) { metricDuplicationOther.increment(); if (decision.doTransform(merge, fixedCount)) { metricDuplicationOtherPerformed.increment(); - new DuplicationOperation(merge, replacements).duplicate(); + new DuplicationOperation(merge, replacements).duplicate(phaseContext); return true; } } @@ -220,10 +222,14 @@ *
  • Determines the complete set of duplicated nodes.
  • *
  • Performs the actual duplication.
  • * + * + * @param phaseContext */ - private void duplicate() { + private void duplicate(PhaseContext phaseContext) { Debug.log("tail duplication at merge %s in %s", merge, graph.method()); + int startMark = graph.getMark(); + ValueAnchorNode anchor = addValueAnchor(); // determine the fixed nodes that should be duplicated (currently: all nodes up until @@ -297,6 +303,7 @@ phi.setMerge(mergeAfter); } } + new CanonicalizerPhase(null, graph.getNewNodes(startMark)).apply(graph, phaseContext); Debug.dump(graph, "After tail duplication at %s", merge); } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Fri Apr 26 22:44:05 2013 +0200 @@ -57,8 +57,7 @@ */ @Snippet public static int f2i(float input, int result) { - if (result == Integer.MIN_VALUE) { - probability(NOT_FREQUENT_PROBABILITY); + if (probability(SLOW_PATH_PROBABILITY, result == Integer.MIN_VALUE)) { if (Float.isNaN(input)) { // input is NaN -> return 0 return 0; @@ -83,8 +82,7 @@ */ @Snippet public static long f2l(float input, long result) { - if (result == Long.MIN_VALUE) { - probability(NOT_FREQUENT_PROBABILITY); + if (probability(SLOW_PATH_PROBABILITY, result == Long.MIN_VALUE)) { if (Float.isNaN(input)) { // input is NaN -> return 0 return 0; @@ -109,8 +107,7 @@ */ @Snippet public static int d2i(double input, int result) { - if (result == Integer.MIN_VALUE) { - probability(NOT_FREQUENT_PROBABILITY); + if (probability(SLOW_PATH_PROBABILITY, result == Integer.MIN_VALUE)) { if (Double.isNaN(input)) { // input is NaN -> return 0 return 0; @@ -135,8 +132,7 @@ */ @Snippet public static long d2l(double input, long result) { - if (result == Long.MIN_VALUE) { - probability(NOT_FREQUENT_PROBABILITY); + if (probability(SLOW_PATH_PROBABILITY, result == Long.MIN_VALUE)) { if (Double.isNaN(input)) { // input is NaN -> return 0 return 0; diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Fri Apr 26 22:44:05 2013 +0200 @@ -282,6 +282,7 @@ if (!SnippetTemplate.hasConstantParameter(method)) { NodeIntrinsificationVerificationPhase.verify(graph); } + new ConvertDeoptimizeToGuardPhase().apply(graph); if (original == null) { new SnippetFrameStateCleanupPhase().apply(graph); diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BranchProbabilityNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BranchProbabilityNode.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BranchProbabilityNode.java Fri Apr 26 22:44:05 2013 +0200 @@ -22,17 +22,17 @@ */ package com.oracle.graal.replacements.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.util.*; /** * Instances of this node class will look for a preceding if node and put the given probability into * the if node's taken probability. Then the branch probability node will be removed. This node is * intended primarily for snippets, so that they can define their fast and slow paths. */ -public class BranchProbabilityNode extends FixedWithNextNode implements Simplifiable { +public class BranchProbabilityNode extends FloatingNode implements Canonicalizable, Lowerable { public static final double LIKELY_PROBABILITY = 0.6; public static final double NOT_LIKELY_PROBABILITY = 1 - LIKELY_PROBABILITY; @@ -43,41 +43,80 @@ public static final double FAST_PATH_PROBABILITY = 0.99; public static final double SLOW_PATH_PROBABILITY = 1 - FAST_PATH_PROBABILITY; - public static final double NOT_DEOPT_PATH_PROBABILITY = 0.999; - public static final double DEOPT_PATH_PROBABILITY = 1 - NOT_DEOPT_PATH_PROBABILITY; + public static final double VERY_FAST_DEOPT_PATH_PROBABILITY = 0.999; + public static final double VERY_SLOW_PATH_PROBABILITY = 1 - VERY_FAST_DEOPT_PATH_PROBABILITY; - private final double probability; + @Input private ValueNode probability; + @Input private ValueNode condition; - public BranchProbabilityNode(double probability) { - super(StampFactory.forVoid()); - assert probability >= 0 && probability <= 1; + public BranchProbabilityNode(ValueNode probability, ValueNode condition) { + super(condition.stamp()); this.probability = probability; + this.condition = condition; + } + + public ValueNode getProbability() { + return probability; + } + + public ValueNode getCondition() { + return condition; } @Override - public void simplify(SimplifierTool tool) { - FixedNode current = this; - while (!(current instanceof BeginNode)) { - current = (FixedNode) current.predecessor(); + public ValueNode canonical(CanonicalizerTool tool) { + if (probability.isConstant()) { + double probabilityValue = probability.asConstant().asDouble(); + if (probabilityValue < 0.0) { + throw new GraalInternalError("A negative probability of " + probabilityValue + " is not allowed!"); + } else if (probabilityValue > 1.0) { + throw new GraalInternalError("A probability of more than 1.0 (" + probabilityValue + ") is not allowed!"); + } + boolean couldSet = false; + for (IntegerEqualsNode node : this.usages().filter(IntegerEqualsNode.class)) { + if (node.condition() == Condition.EQ) { + ValueNode other = node.x(); + if (node.x() == this) { + other = node.y(); + } + if (other.isConstant()) { + double probabilityToSet = probabilityValue; + if (other.asConstant().asInt() == 0) { + probabilityToSet = 1.0 - probabilityToSet; + } + for (IfNode ifNodeUsages : node.usages().filter(IfNode.class)) { + couldSet = true; + ifNodeUsages.setTrueSuccessorProbability(probabilityToSet); + } + } + } + } + if (!couldSet) { + throw new GraalInternalError("Wrong usage of branch probability injection!"); + } + return condition; } - BeginNode begin = (BeginNode) current; - assert begin.predecessor() instanceof IfNode : "explicit branch probability cannot follow a merge, only if nodes"; - IfNode ifNode = (IfNode) begin.predecessor(); - if (ifNode.trueSuccessor() == begin) { - ifNode.setTrueSuccessorProbability(probability); - } else { - ifNode.setTrueSuccessorProbability(1 - probability); - } - - FixedNode next = next(); - setNext(null); - ((FixedWithNextNode) predecessor()).setNext(next); - GraphUtil.killCFG(this); + return this; } - @SuppressWarnings("unused") + /** + * This intrinsic should only be used for the condition of an if statement. The parameter + * condition should also only denote a simple condition and not a combined condition involving + * && or || operators. It injects the probability of the condition into the if statement. + * + * @param probability the probability that the given condition is true as a double value between + * 0.0 and 1.0. + * @param condition the simple condition without any && or || operators + * @return the condition + */ @NodeIntrinsic - public static void probability(@ConstantNodeParameter double probability) { + public static boolean probability(double probability, boolean condition) { + assert probability >= 0.0 && probability <= 1.0; + return condition; } + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + throw new GraalInternalError("Branch probability could not be injected, because the probability value did not reduce to a constant value."); + } } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Fri Apr 26 22:44:05 2013 +0200 @@ -71,6 +71,7 @@ StructuredGraph snippetGraph = getSnippetGraph(tool); InvokeNode invoke = replaceWithInvoke(); + assert invoke.verify(); if (snippetGraph != null) { InliningUtil.inline(invoke, snippetGraph, false); diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java Fri Apr 26 22:44:05 2013 +0200 @@ -115,7 +115,7 @@ @Override public Object execute(VirtualFrame frame) { invocationCount++; - return ((TestArguments) frame.getArguments()).get(index); + return frame.getArguments(TestArguments.class).get(index); } } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java Fri Apr 26 22:44:05 2013 +0200 @@ -35,7 +35,7 @@ * A guest language can pass its own custom arguments when invoking a Truffle method by creating a * subclass of {@link Arguments}. When invoking a call target with * {@link CallTarget#call(Arguments)}, the arguments can be passed. A Truffle node can access the - * arguments passed into the Truffle method by using {@link VirtualFrame#getArguments()}. + * arguments passed into the Truffle method by using {@link VirtualFrame#getArguments}. *

    * *

    @@ -97,7 +97,7 @@ } int execute(VirtualFrame frame) { - return ((TestArguments) frame.getArguments()).values[index]; + return frame.getArguments(TestArguments.class).values[index]; } } } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java Fri Apr 26 22:44:05 2013 +0200 @@ -34,7 +34,7 @@ *

    * Dynamically typed languages can speculate on the type of a frame slot and only fall back at run * time to a more generic type if necessary. The new type of a frame slot can be set using the - * {@link FrameSlot#setType(Class)} method. + * {@link FrameSlot#setKind(FrameSlotKind)} method. *

    * *

    @@ -48,13 +48,13 @@ public void test() { TruffleRuntime runtime = Truffle.getRuntime(); FrameDescriptor frameDescriptor = new FrameDescriptor(); - FrameSlot slot = frameDescriptor.addFrameSlot("localVar", int.class); + FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int); TestRootNode rootNode = new TestRootNode(new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot)); CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor); - Assert.assertEquals(int.class, slot.getType()); + Assert.assertEquals(FrameSlotKind.Int, slot.getKind()); Object result = target.call(); Assert.assertEquals("42", result); - Assert.assertEquals(Object.class, slot.getType()); + Assert.assertEquals(FrameSlotKind.Object, slot.getKind()); } class TestRootNode extends RootNode { diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java Fri Apr 26 22:44:05 2013 +0200 @@ -35,9 +35,9 @@ * The frame is the preferred data structure for passing values between nodes. It can in particular * be used for storing the values of local variables of the guest language. The * {@link FrameDescriptor} represents the current structure of the frame. The method - * {@link FrameDescriptor#addFrameSlot(Object, Class)} can be used to create predefined frame slots. - * The setter and getter methods in the {@link Frame} class can be used to access the current value - * of a particular frame slot. + * {@link FrameDescriptor#addFrameSlot(Object, FrameSlotKind)} can be used to create predefined + * frame slots. The setter and getter methods in the {@link Frame} class can be used to access the + * current value of a particular frame slot. *

    * *

    @@ -64,7 +64,7 @@ public void test() { TruffleRuntime runtime = Truffle.getRuntime(); FrameDescriptor frameDescriptor = new FrameDescriptor(); - FrameSlot slot = frameDescriptor.addFrameSlot("localVar", int.class); + FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int); TestRootNode rootNode = new TestRootNode(new AssignLocal(slot), new ReadLocal(slot)); CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor); Object result = target.call(); diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java Fri Apr 26 22:44:05 2013 +0200 @@ -47,13 +47,13 @@ public void test() { TruffleRuntime runtime = Truffle.getRuntime(); FrameDescriptor frameDescriptor = new FrameDescriptor(); - FrameSlot slot = frameDescriptor.addFrameSlot("localVar", int.class); + FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int); TestRootNode rootNode = new TestRootNode(new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot)); CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor); - Assert.assertEquals(int.class, slot.getType()); + Assert.assertEquals(FrameSlotKind.Int, slot.getKind()); Object result = target.call(); Assert.assertEquals("42", result); - Assert.assertEquals(Object.class, slot.getType()); + Assert.assertEquals(FrameSlotKind.Object, slot.getKind()); } class TestRootNode extends RootNode { diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Fri Apr 26 22:44:05 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.api; +import java.lang.annotation.*; import java.util.concurrent.*; /** @@ -30,7 +31,11 @@ */ public class CompilerDirectives { - private static final double SLOWPATH_PROBABILITY = 0.0001; + public static final double LIKELY_PROBABILITY = 0.75; + public static final double UNLIKELY_PROBABILITY = 1.0 - LIKELY_PROBABILITY; + + public static final double SLOWPATH_PROBABILITY = 0.0001; + public static final double FASTPATH_PROBABILITY = 1.0 - SLOWPATH_PROBABILITY; /** * Directive for the compiler to discontinue compilation at this code position and instead @@ -62,20 +67,38 @@ } /** - * Directive for the compiler that the current path has a very low probability to be executed. - */ - public static void slowpath() { - injectBranchProbability(SLOWPATH_PROBABILITY); - } - - /** - * Injects a probability for the current path into the probability information of the - * immediately preceeding branch instruction. + * Injects a probability for the given condition into the probability information of the + * immediately succeeding branch instruction for the condition. The probability must be a value + * between 0.0 and 1.0 (inclusive). The condition should not be a combined condition. + * + * Example usage immediately before an if statement (it specifies that the likelihood for a to + * be greater than b is 90%): + * + * + * if (injectBranchProbability(0.9, a > b)) { + * // ... + * } + * + * + * Example usage for a combined condition (it specifies that the likelihood for a to be greater + * than b is 90% and under the assumption that this is true, the likelihood for a being 0 is + * 10%): + * + * + * if (injectBranchProbability(0.9, a > b) && injectBranchProbability(0.1, a == 0)) { + * // ... + * } + * + * + * There are predefined constants for commonly used probabilities (see + * {@link #LIKELY_PROBABILITY} , {@link #UNLIKELY_PROBABILITY}, {@link #SLOWPATH_PROBABILITY}, + * {@link #FASTPATH_PROBABILITY} ). * * @param probability the probability value between 0.0 and 1.0 that should be injected */ - public static void injectBranchProbability(double probability) { + public static boolean injectBranchProbability(double probability, boolean condition) { assert probability >= 0.0 && probability <= 1.0; + return condition; } /** @@ -85,4 +108,13 @@ */ public static void bailout(String reason) { } + + /** + * Marks fields that should be considered final for a Truffle compilation although they are not + * final while executing in the interpreter. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD}) + public @interface CompilationFinal { + } } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java Fri Apr 26 22:44:05 2013 +0200 @@ -117,4 +117,10 @@ public final String getCode() { return getSource().getCode().substring(charIndex, charLength); } + + @Override + public String toString() { + return String.format("%s:%d", source.getName(), startLine); + } + } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java Fri Apr 26 22:44:05 2013 +0200 @@ -36,9 +36,16 @@ FrameDescriptor getFrameDescriptor(); /** + * Retrieves the arguments object from this frame. The runtime assumes that the arguments object + * is never null. Additionally, the runtime may assume that the given parameter indicating the + * class of the arguments object is correct. The runtime is not required to actually check the + * type of the arguments object. The parameter must be a value that can be reduced to a compile + * time constant. + * + * @param clazz the known type of the arguments object as a compile time constant * @return the arguments used when calling this method */ - Arguments getArguments(); + T getArguments(Class clazz); /** * Read access to a local variable of type {@link Object}. diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java Fri Apr 26 22:44:05 2013 +0200 @@ -53,9 +53,9 @@ return addFrameSlot(identifier, null); } - public FrameSlot addFrameSlot(Object identifier, Class type) { + public FrameSlot addFrameSlot(Object identifier, FrameSlotKind kind) { assert !identifierToSlotMap.containsKey(identifier); - FrameSlotImpl slot = new FrameSlotImpl(this, identifier, slots.size(), type); + FrameSlotImpl slot = new FrameSlotImpl(this, identifier, slots.size(), kind); slots.add(slot); identifierToSlotMap.put(identifier, slot); updateVersion(); @@ -74,12 +74,12 @@ return addFrameSlot(identifier); } - public FrameSlot findOrAddFrameSlot(Object identifier, Class type) { + public FrameSlot findOrAddFrameSlot(Object identifier, FrameSlotKind kind) { FrameSlot result = findFrameSlot(identifier); if (result != null) { return result; } - return addFrameSlot(identifier, type); + return addFrameSlot(identifier, kind); } public int getSize() { diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java Fri Apr 26 22:44:05 2013 +0200 @@ -31,9 +31,9 @@ int getIndex(); - Class getType(); + FrameSlotKind getKind(); - void setType(Class type); + void setKind(FrameSlotKind kind); FrameDescriptor getFrameDescriptor(); } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java Fri Apr 26 22:44:05 2013 +0200 @@ -27,13 +27,13 @@ private final FrameDescriptor descriptor; private final Object identifier; private final int index; - private Class type; + private FrameSlotKind kind; - protected FrameSlotImpl(FrameDescriptor descriptor, Object identifier, int index, Class type) { + protected FrameSlotImpl(FrameDescriptor descriptor, Object identifier, int index, FrameSlotKind kind) { this.descriptor = descriptor; this.identifier = identifier; this.index = index; - this.type = type; + this.kind = kind; } public Object getIdentifier() { @@ -44,19 +44,19 @@ return index; } - public Class getType() { - return type; + public FrameSlotKind getKind() { + return kind; } - public void setType(final Class type) { - assert this.type != type; - this.type = type; + public void setKind(final FrameSlotKind kind) { + assert this.kind != kind; + this.kind = kind; this.descriptor.updateVersion(); } @Override public String toString() { - return "[" + index + "," + identifier + "," + type + "]"; + return "[" + index + "," + identifier + "," + kind + "]"; } @Override diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotKind.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotKind.java Fri Apr 26 22:44:05 2013 +0200 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.frame; + +public enum FrameSlotKind { + Illegal, Object, Long, Int, Double, Float, Boolean; +} diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java Fri Apr 26 22:44:05 2013 +0200 @@ -33,8 +33,8 @@ * @param value the new value of the local variable */ public static void setObjectSafe(Frame frame, FrameSlot slot, Object value) { - if (slot.getType() != Object.class) { - slot.setType(Object.class); + if (slot.getKind() != FrameSlotKind.Object) { + slot.setKind(FrameSlotKind.Object); } try { frame.setObject(slot, value); @@ -52,8 +52,8 @@ * @param value the new value of the local variable */ public static void setBooleanSafe(Frame frame, FrameSlot slot, boolean value) { - if (slot.getType() != boolean.class) { - slot.setType(boolean.class); + if (slot.getKind() != FrameSlotKind.Boolean) { + slot.setKind(FrameSlotKind.Boolean); } try { frame.setBoolean(slot, value); @@ -71,8 +71,8 @@ * @param value the new value of the local variable */ public static void setIntSafe(Frame frame, FrameSlot slot, int value) { - if (slot.getType() != int.class) { - slot.setType(int.class); + if (slot.getKind() != FrameSlotKind.Int) { + slot.setKind(FrameSlotKind.Int); } try { frame.setInt(slot, value); @@ -90,8 +90,8 @@ * @param value the new value of the local variable */ public static void setLongSafe(Frame frame, FrameSlot slot, long value) { - if (slot.getType() != long.class) { - slot.setType(long.class); + if (slot.getKind() != FrameSlotKind.Long) { + slot.setKind(FrameSlotKind.Long); } try { frame.setLong(slot, value); @@ -109,8 +109,8 @@ * @param value the new value of the local variable */ public static void setFloatSafe(Frame frame, FrameSlot slot, float value) { - if (slot.getType() != float.class) { - slot.setType(float.class); + if (slot.getKind() != FrameSlotKind.Float) { + slot.setKind(FrameSlotKind.Float); } try { frame.setFloat(slot, value); @@ -128,8 +128,8 @@ * @param value the new value of the local variable */ public static void setDoubleSafe(Frame frame, FrameSlot slot, double value) { - if (slot.getType() != double.class) { - slot.setType(double.class); + if (slot.getKind() != FrameSlotKind.Double) { + slot.setKind(FrameSlotKind.Double); } try { frame.setDouble(slot, value); diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java Fri Apr 26 22:44:05 2013 +0200 @@ -38,9 +38,10 @@ this.arguments = arguments; } + @SuppressWarnings("unchecked") @Override - public Arguments getArguments() { - return arguments; + public T getArguments(Class clazz) { + return (T) arguments; } @Override diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java Fri Apr 26 22:44:05 2013 +0200 @@ -34,8 +34,8 @@ } @Override - public Arguments getArguments() { - return wrapped.getArguments(); + public T getArguments(Class clazz) { + return wrapped.getArguments(clazz); } @Override diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Fri Apr 26 22:44:05 2013 +0200 @@ -33,19 +33,20 @@ private final PackedFrame caller; private final Arguments arguments; private Object[] locals; - private Class[] tags; + private byte[] tags; public DefaultVirtualFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments arguments) { this.descriptor = descriptor; this.caller = caller; this.arguments = arguments; this.locals = new Object[descriptor.getSize()]; - this.tags = new Class[descriptor.getSize()]; + this.tags = new byte[descriptor.getSize()]; } + @SuppressWarnings("unchecked") @Override - public Arguments getArguments() { - return arguments; + public T getArguments(Class clazz) { + return (T) arguments; } @Override @@ -65,73 +66,73 @@ @Override public Object getObject(FrameSlot slot) throws FrameSlotTypeException { - verifyGet(slot, Object.class); + verifyGet(slot, FrameSlotKind.Object); return locals[slot.getIndex()]; } @Override public void setObject(FrameSlot slot, Object value) throws FrameSlotTypeException { - verifySet(slot, Object.class); + verifySet(slot, FrameSlotKind.Object); locals[slot.getIndex()] = value; } @Override public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException { - verifyGet(slot, boolean.class); + verifyGet(slot, FrameSlotKind.Boolean); return (boolean) locals[slot.getIndex()]; } @Override public void setBoolean(FrameSlot slot, boolean value) throws FrameSlotTypeException { - verifySet(slot, boolean.class); + verifySet(slot, FrameSlotKind.Boolean); locals[slot.getIndex()] = value; } @Override public int getInt(FrameSlot slot) throws FrameSlotTypeException { - verifyGet(slot, int.class); + verifyGet(slot, FrameSlotKind.Int); return (int) locals[slot.getIndex()]; } @Override public void setInt(FrameSlot slot, int value) throws FrameSlotTypeException { - verifySet(slot, int.class); + verifySet(slot, FrameSlotKind.Int); locals[slot.getIndex()] = value; } @Override public long getLong(FrameSlot slot) throws FrameSlotTypeException { - verifyGet(slot, long.class); + verifyGet(slot, FrameSlotKind.Long); return (long) locals[slot.getIndex()]; } @Override public void setLong(FrameSlot slot, long value) throws FrameSlotTypeException { - verifySet(slot, long.class); + verifySet(slot, FrameSlotKind.Long); locals[slot.getIndex()] = value; } @Override public float getFloat(FrameSlot slot) throws FrameSlotTypeException { - verifyGet(slot, float.class); + verifyGet(slot, FrameSlotKind.Float); return (float) locals[slot.getIndex()]; } @Override public void setFloat(FrameSlot slot, float value) throws FrameSlotTypeException { - verifySet(slot, float.class); + verifySet(slot, FrameSlotKind.Float); locals[slot.getIndex()] = value; } @Override public double getDouble(FrameSlot slot) throws FrameSlotTypeException { - verifyGet(slot, double.class); + verifyGet(slot, FrameSlotKind.Double); return (double) locals[slot.getIndex()]; } @Override public void setDouble(FrameSlot slot, double value) throws FrameSlotTypeException { - verifySet(slot, double.class); + verifySet(slot, FrameSlotKind.Double); locals[slot.getIndex()] = value; } @@ -147,19 +148,19 @@ assert index >= 0 && index < descriptor.getSize(); return descriptor.getTypeConversion().getDefaultValue(); } - Class tag = tags[index]; - if (tag == null) { + byte tag = tags[index]; + if (tag == FrameSlotKind.Illegal.ordinal()) { return descriptor.getTypeConversion().getDefaultValue(); } else { return locals[index]; } } - private void verifySet(FrameSlot slot, Class accessType) throws FrameSlotTypeException { - Class slotType = slot.getType(); - if (slotType != accessType) { - if (slotType == null) { - slot.setType(accessType); + private void verifySet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { + FrameSlotKind slotKind = slot.getKind(); + if (slotKind != accessKind) { + if (slotKind == FrameSlotKind.Illegal) { + slot.setKind(accessKind); } else { throw new FrameSlotTypeException(); } @@ -168,14 +169,14 @@ if (slotIndex >= tags.length) { resize(); } - tags[slotIndex] = accessType; + tags[slotIndex] = (byte) accessKind.ordinal(); } - private void verifyGet(FrameSlot slot, Class accessType) throws FrameSlotTypeException { - Class slotType = slot.getType(); - if (slotType != accessType) { - if (slotType == null && accessType == Object.class) { - slot.setType(Object.class); + private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { + FrameSlotKind slotKind = slot.getKind(); + if (slotKind != accessKind) { + if (slotKind == FrameSlotKind.Illegal && accessKind == FrameSlotKind.Object) { + slot.setKind(FrameSlotKind.Object); this.setObject(slot, descriptor.getTypeConversion().getDefaultValue()); } else { throw new FrameSlotTypeException(); @@ -185,9 +186,9 @@ if (slotIndex >= tags.length) { resize(); } - if (tags[slotIndex] != accessType) { + if (tags[slotIndex] != accessKind.ordinal()) { descriptor.getTypeConversion().updateFrameSlot(this, slot, getValue(slot)); - if (tags[slotIndex] != accessType) { + if (tags[slotIndex] != accessKind.ordinal()) { throw new FrameSlotTypeException(); } } diff -r 52fde777a605 -r f43d04388815 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java Fri Apr 26 22:43:37 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java Fri Apr 26 22:44:05 2013 +0200 @@ -59,7 +59,7 @@ } public TypedNode createLocal(String name) { - return ReadLocalNodeFactory.create(frameDescriptor.findOrAddFrameSlot(name, int.class)); + return ReadLocalNodeFactory.create(frameDescriptor.findOrAddFrameSlot(name, FrameSlotKind.Int)); } public TypedNode createStringLiteral(String value) { @@ -67,7 +67,7 @@ } public StatementNode createAssignment(String name, TypedNode right) { - return WriteLocalNodeFactory.create(frameDescriptor.findOrAddFrameSlot(name, int.class), right); + return WriteLocalNodeFactory.create(frameDescriptor.findOrAddFrameSlot(name, FrameSlotKind.Int), right); } public StatementNode createPrint(List expressions) { @@ -123,7 +123,7 @@ } public StatementNode createReturn(TypedNode value) { - FrameSlot slot = frameDescriptor.findOrAddFrameSlot("", int.class); + FrameSlot slot = frameDescriptor.findOrAddFrameSlot("", FrameSlotKind.Int); if (returnValue == null) { returnValue = ReadLocalNodeFactory.create(slot); } diff -r 52fde777a605 -r f43d04388815 mx/sanitycheck.py --- a/mx/sanitycheck.py Fri Apr 26 22:43:37 2013 +0200 +++ b/mx/sanitycheck.py Fri Apr 26 22:44:05 2013 +0200 @@ -47,7 +47,8 @@ } dacapoScalaSanityWarmup = { - 'actors': [0, 0, 2, 8, 10], +# (tw) actors sometimes fails verification; hardly reproducible + 'actors': [0, 0, 0, 0, 0], # (lstadler) apparat was disabled due to a deadlock which I think is the benchmarks fault. 'apparat': [0, 0, 0, 0, 0], 'factorie': [0, 0, 2, 5, 5],