# HG changeset patch # User Christian Humer # Date 1404496108 -7200 # Node ID e863be932518e5dd425d239d02ac1e4265d646d1 # Parent 7f862f0ab1bca157693ce4327cbd2b07e149ec6e Fixed line delimiters. diff -r 7f862f0ab1bc -r e863be932518 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategy.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategy.java Fri Jul 04 18:56:54 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategy.java Fri Jul 04 19:48:28 2014 +0200 @@ -1,80 +1,80 @@ -package com.oracle.graal.truffle; - -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter; - -public class DefaultTruffleSplittingStrategy implements TruffleSplittingStrategy { - - private final OptimizedDirectCallNode call; - - public DefaultTruffleSplittingStrategy(OptimizedDirectCallNode call) { - this.call = call; - } - - public void beforeCall(Object[] arguments) { - if (call.getCallCount() == 2 && !call.isInlined()) { - if (shouldSplit()) { - forceSplitting(); - } - } - } - - public void forceSplitting() { - if (call.isSplit()) { - return; - } - call.installSplitCallTarget(call.getCallTarget().split()); - } - - public void afterCall(Object returnValue) { - } - - private boolean shouldSplit() { - if (call.getSplitCallTarget() != null) { - return false; - } - if (!TruffleCompilerOptions.TruffleSplitting.getValue()) { - return false; - } - if (!call.isSplittable()) { - return false; - } - OptimizedCallTarget splitTarget = call.getCallTarget(); - int nodeCount = OptimizedCallUtils.countNonTrivialNodes(splitTarget, false); - if (nodeCount > TruffleCompilerOptions.TruffleSplittingMaxCalleeSize.getValue()) { - return false; - } - - // disable recursive splitting for now - OptimizedCallTarget root = (OptimizedCallTarget) call.getRootNode().getCallTarget(); - if (root == splitTarget || root.getSplitSource() == splitTarget) { - // recursive call found - return false; - } - - // max one child call and callCount > 2 and kind of small number of nodes - if (isMaxSingleCall(call)) { - return true; - } - return countPolymorphic(call) >= 1; - } - - private static boolean isMaxSingleCall(OptimizedDirectCallNode call) { - return NodeUtil.countNodes(call.getCurrentCallTarget().getRootNode(), new NodeCountFilter() { - public boolean isCounted(Node node) { - return node instanceof DirectCallNode; - } - }) <= 1; - } - - private static int countPolymorphic(OptimizedDirectCallNode call) { - return NodeUtil.countNodes(call.getCurrentCallTarget().getRootNode(), new NodeCountFilter() { - public boolean isCounted(Node node) { - NodeCost cost = node.getCost(); - boolean polymorphic = cost == NodeCost.POLYMORPHIC || cost == NodeCost.MEGAMORPHIC; - return polymorphic; - } - }); - } - -} +package com.oracle.graal.truffle; + +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter; + +public class DefaultTruffleSplittingStrategy implements TruffleSplittingStrategy { + + private final OptimizedDirectCallNode call; + + public DefaultTruffleSplittingStrategy(OptimizedDirectCallNode call) { + this.call = call; + } + + public void beforeCall(Object[] arguments) { + if (call.getCallCount() == 2 && !call.isInlined()) { + if (shouldSplit()) { + forceSplitting(); + } + } + } + + public void forceSplitting() { + if (call.isSplit()) { + return; + } + call.installSplitCallTarget(call.getCallTarget().split()); + } + + public void afterCall(Object returnValue) { + } + + private boolean shouldSplit() { + if (call.getSplitCallTarget() != null) { + return false; + } + if (!TruffleCompilerOptions.TruffleSplitting.getValue()) { + return false; + } + if (!call.isSplittable()) { + return false; + } + OptimizedCallTarget splitTarget = call.getCallTarget(); + int nodeCount = OptimizedCallUtils.countNonTrivialNodes(splitTarget, false); + if (nodeCount > TruffleCompilerOptions.TruffleSplittingMaxCalleeSize.getValue()) { + return false; + } + + // disable recursive splitting for now + OptimizedCallTarget root = (OptimizedCallTarget) call.getRootNode().getCallTarget(); + if (root == splitTarget || root.getSplitSource() == splitTarget) { + // recursive call found + return false; + } + + // max one child call and callCount > 2 and kind of small number of nodes + if (isMaxSingleCall(call)) { + return true; + } + return countPolymorphic(call) >= 1; + } + + private static boolean isMaxSingleCall(OptimizedDirectCallNode call) { + return NodeUtil.countNodes(call.getCurrentCallTarget().getRootNode(), new NodeCountFilter() { + public boolean isCounted(Node node) { + return node instanceof DirectCallNode; + } + }) <= 1; + } + + private static int countPolymorphic(OptimizedDirectCallNode call) { + return NodeUtil.countNodes(call.getCurrentCallTarget().getRootNode(), new NodeCountFilter() { + public boolean isCounted(Node node) { + NodeCost cost = node.getCost(); + boolean polymorphic = cost == NodeCost.POLYMORPHIC || cost == NodeCost.MEGAMORPHIC; + return polymorphic; + } + }); + } + +} diff -r 7f862f0ab1bc -r e863be932518 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategyNew.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategyNew.java Fri Jul 04 18:56:54 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleSplittingStrategyNew.java Fri Jul 04 19:48:28 2014 +0200 @@ -1,179 +1,179 @@ -package com.oracle.graal.truffle; - -import java.util.*; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.NodeUtil.*; - -public class DefaultTruffleSplittingStrategyNew implements TruffleSplittingStrategy { - private static int splitChangeCount; - - private final int splitStart; - private final OptimizedDirectCallNode call; - private final boolean splittingEnabled; - private boolean splittingForced; - private TruffleStamp argumentStamp; - - public DefaultTruffleSplittingStrategyNew(OptimizedDirectCallNode call) { - this.call = call; - this.splitStart = TruffleCompilerOptions.TruffleSplittingStartCallCount.getValue(); - this.splittingEnabled = isSplittingEnabled(); - this.argumentStamp = DefaultTruffleStamp.getInstance(); - if (TruffleCompilerOptions.TruffleSplittingAggressive.getValue()) { - splittingForced = true; - } - } - - private boolean isSplittingEnabled() { - if (!TruffleCompilerOptions.TruffleSplitting.getValue()) { - return false; - } - if (!call.isSplittable()) { - return false; - } - if (TruffleCompilerOptions.TruffleSplittingAggressive.getValue()) { - return true; - } - int size = OptimizedCallUtils.countNonTrivialNodes(call.getCallTarget(), false); - if (size > TruffleCompilerOptions.TruffleSplittingMaxCalleeSize.getValue()) { - return false; - } - return true; - } - - public void forceSplitting() { - splittingForced = true; - } - - public void beforeCall(Object[] arguments) { - newSplitting(arguments); - } - - public void afterCall(Object returnValue) { - } - - private void newSplitting(Object[] arguments) { - CompilerAsserts.neverPartOfCompilation(); - OptimizedCallTarget currentTarget = call.getCurrentCallTarget(); - - if (splittingForced) { - if (!call.isSplit()) { - call.installSplitCallTarget(currentTarget.split()); - } - return; - } - - TruffleStamp oldStamp = argumentStamp; - TruffleStamp newStamp = oldStamp; - if (!oldStamp.isCompatible(arguments)) { - newStamp = oldStamp.joinValue(arguments); - assert newStamp != oldStamp; - } - - int calls = call.getCallCount(); - - if (oldStamp != newStamp || calls == splitStart || !call.getCurrentCallTarget().getArgumentStamp().equals(newStamp)) { - currentTarget = runSplitIteration(oldStamp, newStamp, calls); - currentTarget.mergeArgumentStamp(newStamp); - argumentStamp = newStamp; - assert call.getCurrentCallTarget().getArgumentStamp().equals(newStamp); - } - } - - private OptimizedCallTarget runSplitIteration(TruffleStamp oldProfile, TruffleStamp newProfile, int calls) { - OptimizedCallTarget currentTarget = call.getCurrentCallTarget(); - if (!splittingEnabled || calls < splitStart) { - return currentTarget; - } - - OptimizedCallTarget target = call.getCallTarget(); - Map profiles = target.getSplitVersions(); - OptimizedCallTarget newTarget = currentTarget; - - boolean split = false; - if (!currentTarget.getArgumentStamp().equals(newProfile)) { - if (target.getArgumentStamp().equals(newProfile)) { - // the original target is compatible again. - // -> we can use the original call target. - newTarget = target; - } else if (currentTarget.getKnownCallSiteCount() == 1 && currentTarget.getArgumentStamp().equals(oldProfile)) { - // we are the only caller + the profile is not polluted by other call sites - // -> reuse the currentTarget but update the profile if necessary - newTarget = currentTarget; - if (currentTarget.getSplitSource() != null) { - profiles.remove(oldProfile); - profiles.put(newProfile, newTarget); - } - } else { - newTarget = profiles.get(newProfile); - if (newTarget == null) { - // in case no compatible target was found we need to split - newTarget = target.split(); - profiles.put(newProfile, newTarget); - split = true; - } - } - } - - call.installSplitCallTarget(newTarget); - - if (split && TruffleCompilerOptions.TraceTruffleSplitting.getValue()) { - traceSplit(currentTarget.getSplitSource() != null ? oldProfile : currentTarget.getArgumentStamp(), newProfile); - } - - cleanup(currentTarget); - return newTarget; - } - - private void traceSplit(TruffleStamp oldStamp, TruffleStamp newStamp) { - OptimizedCallTarget callTarget = call.getCallTarget(); - Map splitTargets = callTarget.getSplitVersions(); - String label = String.format("split %3s-%-4s-%-4s ", splitChangeCount++, call.getCurrentCallTarget().getSplitIndex(), call.getCallCount()); - OptimizedCallTargetLog.log(0, label, callTarget.toString(), callTarget.getDebugProperties()); - logProfile(callTarget.getArgumentStamp(), callTarget, oldStamp, newStamp); - for (TruffleStamp profile : splitTargets.keySet()) { - logProfile(profile, splitTargets.get(profile), oldStamp, newStamp); - } - } - - private static void logProfile(TruffleStamp stamp, OptimizedCallTarget target, TruffleStamp oldStamp, TruffleStamp newStamp) { - String id = String.format("@%8h %s", target.hashCode(), target.getSplitSource() == null ? "orig." : "split"); - String plusMinus = stamp.equals(newStamp) ? "+ " : (stamp.equals(oldStamp) ? "- " : ""); - System.out.printf("%16s%-20sCallers: %3d, Nodes:%10s %s%n", plusMinus, id, target.getKnownCallSiteCount(), // - String.format("%d (%d/%d)", count(target, NodeCost.MONOMORPHIC), count(target, NodeCost.POLYMORPHIC), count(target, NodeCost.MEGAMORPHIC)),// - stamp); - } - - private static int count(OptimizedCallTarget target, final NodeCost otherCost) { - return NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() { - public boolean isCounted(Node node) { - return node.getCost() == otherCost; - } - }); - } - - private static void cleanup(OptimizedCallTarget currentTarget) { - if (currentTarget.getKnownCallSiteCount() == 0 && currentTarget.getSplitSource() != null) { - OptimizedCallTarget removed = currentTarget.getSplitSource().getSplitVersions().remove(currentTarget.getArgumentStamp()); - if (removed != null) { - disposeTarget(removed); - } - } - } - - private static void disposeTarget(OptimizedCallTarget removed) { - removed.getRootNode().accept(new NodeVisitor() { - public boolean visit(Node node) { - if (node instanceof OptimizedDirectCallNode) { - OptimizedDirectCallNode call = ((OptimizedDirectCallNode) node); - call.getCurrentCallTarget().decrementKnownCallSites(); - cleanup(call.getCurrentCallTarget()); - } - return true; - } - }); - - } - -} +package com.oracle.graal.truffle; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.*; + +public class DefaultTruffleSplittingStrategyNew implements TruffleSplittingStrategy { + private static int splitChangeCount; + + private final int splitStart; + private final OptimizedDirectCallNode call; + private final boolean splittingEnabled; + private boolean splittingForced; + private TruffleStamp argumentStamp; + + public DefaultTruffleSplittingStrategyNew(OptimizedDirectCallNode call) { + this.call = call; + this.splitStart = TruffleCompilerOptions.TruffleSplittingStartCallCount.getValue(); + this.splittingEnabled = isSplittingEnabled(); + this.argumentStamp = DefaultTruffleStamp.getInstance(); + if (TruffleCompilerOptions.TruffleSplittingAggressive.getValue()) { + splittingForced = true; + } + } + + private boolean isSplittingEnabled() { + if (!TruffleCompilerOptions.TruffleSplitting.getValue()) { + return false; + } + if (!call.isSplittable()) { + return false; + } + if (TruffleCompilerOptions.TruffleSplittingAggressive.getValue()) { + return true; + } + int size = OptimizedCallUtils.countNonTrivialNodes(call.getCallTarget(), false); + if (size > TruffleCompilerOptions.TruffleSplittingMaxCalleeSize.getValue()) { + return false; + } + return true; + } + + public void forceSplitting() { + splittingForced = true; + } + + public void beforeCall(Object[] arguments) { + newSplitting(arguments); + } + + public void afterCall(Object returnValue) { + } + + private void newSplitting(Object[] arguments) { + CompilerAsserts.neverPartOfCompilation(); + OptimizedCallTarget currentTarget = call.getCurrentCallTarget(); + + if (splittingForced) { + if (!call.isSplit()) { + call.installSplitCallTarget(currentTarget.split()); + } + return; + } + + TruffleStamp oldStamp = argumentStamp; + TruffleStamp newStamp = oldStamp; + if (!oldStamp.isCompatible(arguments)) { + newStamp = oldStamp.joinValue(arguments); + assert newStamp != oldStamp; + } + + int calls = call.getCallCount(); + + if (oldStamp != newStamp || calls == splitStart || !call.getCurrentCallTarget().getArgumentStamp().equals(newStamp)) { + currentTarget = runSplitIteration(oldStamp, newStamp, calls); + currentTarget.mergeArgumentStamp(newStamp); + argumentStamp = newStamp; + assert call.getCurrentCallTarget().getArgumentStamp().equals(newStamp); + } + } + + private OptimizedCallTarget runSplitIteration(TruffleStamp oldProfile, TruffleStamp newProfile, int calls) { + OptimizedCallTarget currentTarget = call.getCurrentCallTarget(); + if (!splittingEnabled || calls < splitStart) { + return currentTarget; + } + + OptimizedCallTarget target = call.getCallTarget(); + Map profiles = target.getSplitVersions(); + OptimizedCallTarget newTarget = currentTarget; + + boolean split = false; + if (!currentTarget.getArgumentStamp().equals(newProfile)) { + if (target.getArgumentStamp().equals(newProfile)) { + // the original target is compatible again. + // -> we can use the original call target. + newTarget = target; + } else if (currentTarget.getKnownCallSiteCount() == 1 && currentTarget.getArgumentStamp().equals(oldProfile)) { + // we are the only caller + the profile is not polluted by other call sites + // -> reuse the currentTarget but update the profile if necessary + newTarget = currentTarget; + if (currentTarget.getSplitSource() != null) { + profiles.remove(oldProfile); + profiles.put(newProfile, newTarget); + } + } else { + newTarget = profiles.get(newProfile); + if (newTarget == null) { + // in case no compatible target was found we need to split + newTarget = target.split(); + profiles.put(newProfile, newTarget); + split = true; + } + } + } + + call.installSplitCallTarget(newTarget); + + if (split && TruffleCompilerOptions.TraceTruffleSplitting.getValue()) { + traceSplit(currentTarget.getSplitSource() != null ? oldProfile : currentTarget.getArgumentStamp(), newProfile); + } + + cleanup(currentTarget); + return newTarget; + } + + private void traceSplit(TruffleStamp oldStamp, TruffleStamp newStamp) { + OptimizedCallTarget callTarget = call.getCallTarget(); + Map splitTargets = callTarget.getSplitVersions(); + String label = String.format("split %3s-%-4s-%-4s ", splitChangeCount++, call.getCurrentCallTarget().getSplitIndex(), call.getCallCount()); + OptimizedCallTargetLog.log(0, label, callTarget.toString(), callTarget.getDebugProperties()); + logProfile(callTarget.getArgumentStamp(), callTarget, oldStamp, newStamp); + for (TruffleStamp profile : splitTargets.keySet()) { + logProfile(profile, splitTargets.get(profile), oldStamp, newStamp); + } + } + + private static void logProfile(TruffleStamp stamp, OptimizedCallTarget target, TruffleStamp oldStamp, TruffleStamp newStamp) { + String id = String.format("@%8h %s", target.hashCode(), target.getSplitSource() == null ? "orig." : "split"); + String plusMinus = stamp.equals(newStamp) ? "+ " : (stamp.equals(oldStamp) ? "- " : ""); + System.out.printf("%16s%-20sCallers: %3d, Nodes:%10s %s%n", plusMinus, id, target.getKnownCallSiteCount(), // + String.format("%d (%d/%d)", count(target, NodeCost.MONOMORPHIC), count(target, NodeCost.POLYMORPHIC), count(target, NodeCost.MEGAMORPHIC)),// + stamp); + } + + private static int count(OptimizedCallTarget target, final NodeCost otherCost) { + return NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() { + public boolean isCounted(Node node) { + return node.getCost() == otherCost; + } + }); + } + + private static void cleanup(OptimizedCallTarget currentTarget) { + if (currentTarget.getKnownCallSiteCount() == 0 && currentTarget.getSplitSource() != null) { + OptimizedCallTarget removed = currentTarget.getSplitSource().getSplitVersions().remove(currentTarget.getArgumentStamp()); + if (removed != null) { + disposeTarget(removed); + } + } + } + + private static void disposeTarget(OptimizedCallTarget removed) { + removed.getRootNode().accept(new NodeVisitor() { + public boolean visit(Node node) { + if (node instanceof OptimizedDirectCallNode) { + OptimizedDirectCallNode call = ((OptimizedDirectCallNode) node); + call.getCurrentCallTarget().decrementKnownCallSites(); + cleanup(call.getCurrentCallTarget()); + } + return true; + } + }); + + } + +} diff -r 7f862f0ab1bc -r e863be932518 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleStamp.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleStamp.java Fri Jul 04 18:56:54 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleStamp.java Fri Jul 04 19:48:28 2014 +0200 @@ -1,501 +1,501 @@ -package com.oracle.graal.truffle; - -import java.util.*; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.nodes.*; - -public final class DefaultTruffleStamp { - - private static final Object NO_TYPE = new Object(); - private static final Class NO_CLASS = new Object[]{}.getClass(); - private static final Object NO_INSTANCE = new Object(); - - private DefaultTruffleStamp() { - // do not instantiate - } - - public static TruffleStamp getInstance() { - return UninitializedStamp.INSTANCE; - } - - private static TruffleStamp createStamp(Object value) { - if (value instanceof Object[]) { - return ArrayStamp.INSTANCE.joinValue(value); - } else if (!useInstanceStamps(value)) { - Object type = getTypeIdentifier(value); - if (type != NO_TYPE) { - return new TypeStamp(value.getClass(), type); - } else { - return new ClassStamp(value.getClass()); - } - } else { - return new InstanceStamp(value); - } - } - - private static boolean useInstanceStamps(Object value) { - if (TruffleCompilerOptions.TruffleSplittingTypeInstanceStamps.getValue()) { - if (value instanceof TypedObject) { - return true; - } - } - if (TruffleCompilerOptions.TruffleSplittingClassInstanceStamps.getValue()) { - return true; - } - return false; - } - - private static Object getTypeIdentifier(Object value) { - if (value instanceof TypedObject) { - return ((TypedObject) value).getTypeIdentifier(); - } - return NO_TYPE; - } - - private static abstract class ValueStamp implements TruffleStamp { - - Class getClazz() { - return NO_CLASS; - } - - Object getType() { - return NO_TYPE; - } - - Object getInstance() { - return NO_INSTANCE; - } - - @Override - public final TruffleStamp joinValue(Object value) { - return join(createStamp(value)); - } - - public final String toStringShort() { - return getClass().getAnnotation(NodeInfo.class).shortName(); - } - - @Override - public String toString() { - return toStringShort(); - } - - } - - @NodeInfo(shortName = "U") - private static final class UninitializedStamp extends ValueStamp { - private static final UninitializedStamp INSTANCE = new UninitializedStamp(); - - @Override - public TruffleStamp join(TruffleStamp p) { - return p; - } - - @Override - public boolean isCompatible(Object value) { - return false; - } - - @Override - public boolean equals(Object obj) { - return obj == INSTANCE; - } - - @Override - public int hashCode() { - return 1; - } - - } - - @NodeInfo(shortName = "I") - private static final class InstanceStamp extends ValueStamp { - - private final Object instance; - private final Class clazz; - private final Object type; - - public InstanceStamp(Object instance) { - this.instance = instance; - this.type = instance != null ? getTypeIdentifier(instance) : NO_TYPE; - this.clazz = instance != null ? instance.getClass() : NO_CLASS; - } - - @Override - public TruffleStamp join(TruffleStamp p) { - if (p instanceof ValueStamp) { - ValueStamp ap = ((ValueStamp) p); - if (ap.getInstance() != NO_INSTANCE) { - if (isCompatible(ap.getInstance())) { - return this; - } - } - if (ap.getType() != NO_TYPE) { - if (type == ap.getType()) { - return new TypeStamp(clazz, type); - } - } - if (ap.getClazz() != NO_CLASS) { - if (clazz == ap.getClazz()) { - return new ClassStamp(clazz); - } - } - } - return GenericStamp.INSTANCE; - } - - @Override - public boolean isCompatible(Object value) { - return instance == value; - } - - @Override - Object getInstance() { - return instance; - } - - @Override - Object getType() { - return type; - } - - @Override - Class getClazz() { - return clazz; - } - - @Override - public boolean equals(Object obj) { - return obj instanceof InstanceStamp && ((InstanceStamp) obj).instance == instance; - } - - @Override - public int hashCode() { - if (instance != null) { - return instance.hashCode(); - } else { - return 31; - } - } - - @Override - public String toString() { - return String.format("%s=0x%8h", toStringShort(), System.identityHashCode(instance)); - } - - } - - @NodeInfo(shortName = "T") - private static final class TypeStamp extends ValueStamp { - - private final Class clazz; - private final Object type; - - public TypeStamp(Class clazz, Object type) { - this.clazz = clazz; - this.type = type; - assert type != NO_TYPE; - } - - @Override - public TruffleStamp join(TruffleStamp p) { - if (p instanceof ValueStamp) { - ValueStamp ap = ((ValueStamp) p); - - if (ap.getType() != NO_TYPE) { - if (type == ap.getType()) { - return this; - } - } - if (ap.getClazz() != NO_CLASS) { - if (clazz == ap.getClazz()) { - return new ClassStamp(clazz); - } - } - - } - return GenericStamp.INSTANCE; - } - - @Override - public boolean isCompatible(Object value) { - return getTypeIdentifier(value) == type; - } - - @Override - Class getClazz() { - return clazz; - } - - @Override - Object getType() { - return type; - } - - @Override - public boolean equals(Object obj) { - return obj instanceof TypeStamp && ((TypeStamp) obj).type == type; - } - - @Override - public int hashCode() { - return type.hashCode(); - } - - @Override - public String toString() { - return String.format("%s=0x%8h", toStringShort(), System.identityHashCode(type)); - } - - } - - @NodeInfo(shortName = "C") - private static final class ClassStamp extends ValueStamp { - - private final Class clazz; - - public ClassStamp(Class clazz) { - this.clazz = clazz; - } - - @Override - public boolean isCompatible(Object value) { - return value.getClass() == clazz; - } - - @Override - public TruffleStamp join(TruffleStamp p) { - if (p instanceof ValueStamp) { - ValueStamp ap = ((ValueStamp) p); - if (ap.getClazz() != NO_CLASS) { - if (clazz == ap.getClazz()) { - return this; - } - } - } - return GenericStamp.INSTANCE; - } - - @Override - public boolean equals(Object obj) { - return obj instanceof ClassStamp && ((ClassStamp) obj).clazz == clazz; - } - - @Override - public int hashCode() { - return clazz.hashCode(); - } - - @Override - Class getClazz() { - return clazz; - } - - @Override - public String toString() { - return String.format("%s=%-10s", toStringShort(), clazz.getSimpleName()); - } - - } - - private final static class ArrayStamp implements TruffleStamp { - - private static final ArrayStamp INSTANCE = new ArrayStamp(getInstance()); - - private static final int MAX_STAMPED_ARGUMENTS = 10; - private static final int GENERIC_LENGTH = -1; - private static final int UNINITIALIZED_LENGTH = -2; - - private final TruffleStamp[] stampArray; - private final int length; - - public ArrayStamp(TruffleStamp stamp) { - this.stampArray = new TruffleStamp[MAX_STAMPED_ARGUMENTS]; - Arrays.fill(this.stampArray, stamp); - this.length = UNINITIALIZED_LENGTH; - } - - public ArrayStamp(TruffleStamp[] profiledTypes, int length) { - this.stampArray = profiledTypes; - this.length = length; - } - - public boolean isCompatible(Object value) { - if (!(value instanceof Object[])) { - return false; - } - Object[] array = (Object[]) value; - if ((length != array.length && length != GENERIC_LENGTH) || length == UNINITIALIZED_LENGTH) { - return false; - } - TruffleStamp[] currentArray = this.stampArray; - for (int i = 0; i < Math.min(array.length, currentArray.length); i++) { - if (!currentArray[i].isCompatible(array[i])) { - return false; - } - } - return true; - } - - public TruffleStamp join(TruffleStamp p) { - if (!(p instanceof ArrayStamp)) { - return GenericStamp.INSTANCE; - } - ArrayStamp other = (ArrayStamp) p; - int newLength = profileLength(other.length); - - TruffleStamp[] newArray = this.stampArray; - TruffleStamp[] otherArray = other.stampArray; - assert newArray.length == otherArray.length; - - for (int i = 0; i < newArray.length; i++) { - TruffleStamp thisStamp = newArray[i]; - TruffleStamp newStamp = thisStamp.join(otherArray[i]); - - if (thisStamp != newStamp) { - if (newArray == this.stampArray) { - newArray = Arrays.copyOf(newArray, newArray.length); - } - newArray[i] = newStamp; - } - } - return create(newArray, newLength); - } - - public TruffleStamp joinValue(Object value) { - if (!(value instanceof Object[])) { - return GenericStamp.INSTANCE; - } - Object[] array = (Object[]) value; - int newLength = profileLength(array.length); - TruffleStamp[] newArray = this.stampArray; - for (int i = 0; i < Math.min(array.length, newArray.length); i++) { - TruffleStamp oldStamp = newArray[i]; - Object newValue = array[i]; - if (!oldStamp.isCompatible(newValue)) { - if (newArray == this.stampArray) { - newArray = Arrays.copyOf(newArray, newArray.length); - } - newArray[i] = oldStamp.joinValue(newValue); - } - } - return create(newArray, newLength); - } - - private TruffleStamp create(TruffleStamp[] newArray, int newLength) { - if (newLength != this.length || newArray != this.stampArray) { - return new ArrayStamp(newArray != null ? newArray : stampArray, newLength); - } else { - return this; - } - } - - private int profileLength(int arrayLength) { - int nextLength = this.length; - switch (nextLength) { - case UNINITIALIZED_LENGTH: - return arrayLength; - case GENERIC_LENGTH: - return nextLength; - default: - if (nextLength != arrayLength) { - if (arrayLength == UNINITIALIZED_LENGTH) { - return nextLength; - } else { - return GENERIC_LENGTH; - } - } else { - return nextLength; - } - } - - } - - @Override - public int hashCode() { - return 31 * (31 + length) + Arrays.hashCode(stampArray); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof ArrayStamp)) { - return false; - } - ArrayStamp a = (ArrayStamp) obj; - if (a.length != length) { - return false; - } - return Arrays.equals(a.stampArray, stampArray); - } - - public String toStringShort() { - if (length == 0) { - return "[]"; - } - StringBuilder b = new StringBuilder("["); - for (TruffleStamp stamp : stampArray) { - if (stamp instanceof UninitializedStamp) { - continue; - } - if (stamp instanceof ValueStamp) { - b.append(((ValueStamp) stamp).toStringShort()); - } else if (stamp instanceof ArrayStamp) { - b.append(((ArrayStamp) stamp).toStringShort()); - } else { - b.append("?"); - } - } - b.append("]"); - - b.append(".").append(formatLength()); - return b.toString(); - } - - @Override - public String toString() { - return "Array(length=" + formatLength() + ", " + Arrays.toString(stampArray) + ")"; - } - - private String formatLength() { - String lengthString; - if (length == GENERIC_LENGTH) { - lengthString = "G"; - } else if (length == UNINITIALIZED_LENGTH) { - lengthString = "U"; - } else { - lengthString = String.valueOf(this.length); - } - return lengthString; - } - - } - - @NodeInfo(shortName = "G") - private static final class GenericStamp extends ValueStamp { - - private static final GenericStamp INSTANCE = new GenericStamp(); - - @Override - public boolean isCompatible(Object value) { - return true; - } - - @Override - public TruffleStamp join(TruffleStamp p) { - return this; - } - - @Override - public boolean equals(Object obj) { - return obj == INSTANCE; - } - - @Override - public int hashCode() { - return 31; - } - - } - -} +package com.oracle.graal.truffle; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.*; + +public final class DefaultTruffleStamp { + + private static final Object NO_TYPE = new Object(); + private static final Class NO_CLASS = new Object[]{}.getClass(); + private static final Object NO_INSTANCE = new Object(); + + private DefaultTruffleStamp() { + // do not instantiate + } + + public static TruffleStamp getInstance() { + return UninitializedStamp.INSTANCE; + } + + private static TruffleStamp createStamp(Object value) { + if (value instanceof Object[]) { + return ArrayStamp.INSTANCE.joinValue(value); + } else if (!useInstanceStamps(value)) { + Object type = getTypeIdentifier(value); + if (type != NO_TYPE) { + return new TypeStamp(value.getClass(), type); + } else { + return new ClassStamp(value.getClass()); + } + } else { + return new InstanceStamp(value); + } + } + + private static boolean useInstanceStamps(Object value) { + if (TruffleCompilerOptions.TruffleSplittingTypeInstanceStamps.getValue()) { + if (value instanceof TypedObject) { + return true; + } + } + if (TruffleCompilerOptions.TruffleSplittingClassInstanceStamps.getValue()) { + return true; + } + return false; + } + + private static Object getTypeIdentifier(Object value) { + if (value instanceof TypedObject) { + return ((TypedObject) value).getTypeIdentifier(); + } + return NO_TYPE; + } + + private static abstract class ValueStamp implements TruffleStamp { + + Class getClazz() { + return NO_CLASS; + } + + Object getType() { + return NO_TYPE; + } + + Object getInstance() { + return NO_INSTANCE; + } + + @Override + public final TruffleStamp joinValue(Object value) { + return join(createStamp(value)); + } + + public final String toStringShort() { + return getClass().getAnnotation(NodeInfo.class).shortName(); + } + + @Override + public String toString() { + return toStringShort(); + } + + } + + @NodeInfo(shortName = "U") + private static final class UninitializedStamp extends ValueStamp { + private static final UninitializedStamp INSTANCE = new UninitializedStamp(); + + @Override + public TruffleStamp join(TruffleStamp p) { + return p; + } + + @Override + public boolean isCompatible(Object value) { + return false; + } + + @Override + public boolean equals(Object obj) { + return obj == INSTANCE; + } + + @Override + public int hashCode() { + return 1; + } + + } + + @NodeInfo(shortName = "I") + private static final class InstanceStamp extends ValueStamp { + + private final Object instance; + private final Class clazz; + private final Object type; + + public InstanceStamp(Object instance) { + this.instance = instance; + this.type = instance != null ? getTypeIdentifier(instance) : NO_TYPE; + this.clazz = instance != null ? instance.getClass() : NO_CLASS; + } + + @Override + public TruffleStamp join(TruffleStamp p) { + if (p instanceof ValueStamp) { + ValueStamp ap = ((ValueStamp) p); + if (ap.getInstance() != NO_INSTANCE) { + if (isCompatible(ap.getInstance())) { + return this; + } + } + if (ap.getType() != NO_TYPE) { + if (type == ap.getType()) { + return new TypeStamp(clazz, type); + } + } + if (ap.getClazz() != NO_CLASS) { + if (clazz == ap.getClazz()) { + return new ClassStamp(clazz); + } + } + } + return GenericStamp.INSTANCE; + } + + @Override + public boolean isCompatible(Object value) { + return instance == value; + } + + @Override + Object getInstance() { + return instance; + } + + @Override + Object getType() { + return type; + } + + @Override + Class getClazz() { + return clazz; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof InstanceStamp && ((InstanceStamp) obj).instance == instance; + } + + @Override + public int hashCode() { + if (instance != null) { + return instance.hashCode(); + } else { + return 31; + } + } + + @Override + public String toString() { + return String.format("%s=0x%8h", toStringShort(), System.identityHashCode(instance)); + } + + } + + @NodeInfo(shortName = "T") + private static final class TypeStamp extends ValueStamp { + + private final Class clazz; + private final Object type; + + public TypeStamp(Class clazz, Object type) { + this.clazz = clazz; + this.type = type; + assert type != NO_TYPE; + } + + @Override + public TruffleStamp join(TruffleStamp p) { + if (p instanceof ValueStamp) { + ValueStamp ap = ((ValueStamp) p); + + if (ap.getType() != NO_TYPE) { + if (type == ap.getType()) { + return this; + } + } + if (ap.getClazz() != NO_CLASS) { + if (clazz == ap.getClazz()) { + return new ClassStamp(clazz); + } + } + + } + return GenericStamp.INSTANCE; + } + + @Override + public boolean isCompatible(Object value) { + return getTypeIdentifier(value) == type; + } + + @Override + Class getClazz() { + return clazz; + } + + @Override + Object getType() { + return type; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof TypeStamp && ((TypeStamp) obj).type == type; + } + + @Override + public int hashCode() { + return type.hashCode(); + } + + @Override + public String toString() { + return String.format("%s=0x%8h", toStringShort(), System.identityHashCode(type)); + } + + } + + @NodeInfo(shortName = "C") + private static final class ClassStamp extends ValueStamp { + + private final Class clazz; + + public ClassStamp(Class clazz) { + this.clazz = clazz; + } + + @Override + public boolean isCompatible(Object value) { + return value.getClass() == clazz; + } + + @Override + public TruffleStamp join(TruffleStamp p) { + if (p instanceof ValueStamp) { + ValueStamp ap = ((ValueStamp) p); + if (ap.getClazz() != NO_CLASS) { + if (clazz == ap.getClazz()) { + return this; + } + } + } + return GenericStamp.INSTANCE; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof ClassStamp && ((ClassStamp) obj).clazz == clazz; + } + + @Override + public int hashCode() { + return clazz.hashCode(); + } + + @Override + Class getClazz() { + return clazz; + } + + @Override + public String toString() { + return String.format("%s=%-10s", toStringShort(), clazz.getSimpleName()); + } + + } + + private final static class ArrayStamp implements TruffleStamp { + + private static final ArrayStamp INSTANCE = new ArrayStamp(getInstance()); + + private static final int MAX_STAMPED_ARGUMENTS = 10; + private static final int GENERIC_LENGTH = -1; + private static final int UNINITIALIZED_LENGTH = -2; + + private final TruffleStamp[] stampArray; + private final int length; + + public ArrayStamp(TruffleStamp stamp) { + this.stampArray = new TruffleStamp[MAX_STAMPED_ARGUMENTS]; + Arrays.fill(this.stampArray, stamp); + this.length = UNINITIALIZED_LENGTH; + } + + public ArrayStamp(TruffleStamp[] profiledTypes, int length) { + this.stampArray = profiledTypes; + this.length = length; + } + + public boolean isCompatible(Object value) { + if (!(value instanceof Object[])) { + return false; + } + Object[] array = (Object[]) value; + if ((length != array.length && length != GENERIC_LENGTH) || length == UNINITIALIZED_LENGTH) { + return false; + } + TruffleStamp[] currentArray = this.stampArray; + for (int i = 0; i < Math.min(array.length, currentArray.length); i++) { + if (!currentArray[i].isCompatible(array[i])) { + return false; + } + } + return true; + } + + public TruffleStamp join(TruffleStamp p) { + if (!(p instanceof ArrayStamp)) { + return GenericStamp.INSTANCE; + } + ArrayStamp other = (ArrayStamp) p; + int newLength = profileLength(other.length); + + TruffleStamp[] newArray = this.stampArray; + TruffleStamp[] otherArray = other.stampArray; + assert newArray.length == otherArray.length; + + for (int i = 0; i < newArray.length; i++) { + TruffleStamp thisStamp = newArray[i]; + TruffleStamp newStamp = thisStamp.join(otherArray[i]); + + if (thisStamp != newStamp) { + if (newArray == this.stampArray) { + newArray = Arrays.copyOf(newArray, newArray.length); + } + newArray[i] = newStamp; + } + } + return create(newArray, newLength); + } + + public TruffleStamp joinValue(Object value) { + if (!(value instanceof Object[])) { + return GenericStamp.INSTANCE; + } + Object[] array = (Object[]) value; + int newLength = profileLength(array.length); + TruffleStamp[] newArray = this.stampArray; + for (int i = 0; i < Math.min(array.length, newArray.length); i++) { + TruffleStamp oldStamp = newArray[i]; + Object newValue = array[i]; + if (!oldStamp.isCompatible(newValue)) { + if (newArray == this.stampArray) { + newArray = Arrays.copyOf(newArray, newArray.length); + } + newArray[i] = oldStamp.joinValue(newValue); + } + } + return create(newArray, newLength); + } + + private TruffleStamp create(TruffleStamp[] newArray, int newLength) { + if (newLength != this.length || newArray != this.stampArray) { + return new ArrayStamp(newArray != null ? newArray : stampArray, newLength); + } else { + return this; + } + } + + private int profileLength(int arrayLength) { + int nextLength = this.length; + switch (nextLength) { + case UNINITIALIZED_LENGTH: + return arrayLength; + case GENERIC_LENGTH: + return nextLength; + default: + if (nextLength != arrayLength) { + if (arrayLength == UNINITIALIZED_LENGTH) { + return nextLength; + } else { + return GENERIC_LENGTH; + } + } else { + return nextLength; + } + } + + } + + @Override + public int hashCode() { + return 31 * (31 + length) + Arrays.hashCode(stampArray); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof ArrayStamp)) { + return false; + } + ArrayStamp a = (ArrayStamp) obj; + if (a.length != length) { + return false; + } + return Arrays.equals(a.stampArray, stampArray); + } + + public String toStringShort() { + if (length == 0) { + return "[]"; + } + StringBuilder b = new StringBuilder("["); + for (TruffleStamp stamp : stampArray) { + if (stamp instanceof UninitializedStamp) { + continue; + } + if (stamp instanceof ValueStamp) { + b.append(((ValueStamp) stamp).toStringShort()); + } else if (stamp instanceof ArrayStamp) { + b.append(((ArrayStamp) stamp).toStringShort()); + } else { + b.append("?"); + } + } + b.append("]"); + + b.append(".").append(formatLength()); + return b.toString(); + } + + @Override + public String toString() { + return "Array(length=" + formatLength() + ", " + Arrays.toString(stampArray) + ")"; + } + + private String formatLength() { + String lengthString; + if (length == GENERIC_LENGTH) { + lengthString = "G"; + } else if (length == UNINITIALIZED_LENGTH) { + lengthString = "U"; + } else { + lengthString = String.valueOf(this.length); + } + return lengthString; + } + + } + + @NodeInfo(shortName = "G") + private static final class GenericStamp extends ValueStamp { + + private static final GenericStamp INSTANCE = new GenericStamp(); + + @Override + public boolean isCompatible(Object value) { + return true; + } + + @Override + public TruffleStamp join(TruffleStamp p) { + return this; + } + + @Override + public boolean equals(Object obj) { + return obj == INSTANCE; + } + + @Override + public int hashCode() { + return 31; + } + + } + +} diff -r 7f862f0ab1bc -r e863be932518 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleSplittingStrategy.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleSplittingStrategy.java Fri Jul 04 18:56:54 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleSplittingStrategy.java Fri Jul 04 19:48:28 2014 +0200 @@ -1,11 +1,11 @@ -package com.oracle.graal.truffle; - -public interface TruffleSplittingStrategy { - - void beforeCall(Object[] arguments); - - void afterCall(Object returnValue); - - void forceSplitting(); - -} +package com.oracle.graal.truffle; + +public interface TruffleSplittingStrategy { + + void beforeCall(Object[] arguments); + + void afterCall(Object returnValue); + + void forceSplitting(); + +} diff -r 7f862f0ab1bc -r e863be932518 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleStamp.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleStamp.java Fri Jul 04 18:56:54 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleStamp.java Fri Jul 04 19:48:28 2014 +0200 @@ -1,16 +1,16 @@ -package com.oracle.graal.truffle; - -/** - * Experimental. - */ -public abstract interface TruffleStamp { - - TruffleStamp join(TruffleStamp p); - - TruffleStamp joinValue(Object value); - - boolean isCompatible(Object value); - - String toStringShort(); - +package com.oracle.graal.truffle; + +/** + * Experimental. + */ +public abstract interface TruffleStamp { + + TruffleStamp join(TruffleStamp p); + + TruffleStamp joinValue(Object value); + + boolean isCompatible(Object value); + + String toStringShort(); + } \ No newline at end of file diff -r 7f862f0ab1bc -r e863be932518 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TypedObject.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TypedObject.java Fri Jul 04 18:56:54 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TypedObject.java Fri Jul 04 19:48:28 2014 +0200 @@ -1,7 +1,7 @@ -package com.oracle.truffle.api; - -public interface TypedObject { - - Object getTypeIdentifier(); - -} +package com.oracle.truffle.api; + +public interface TypedObject { + + Object getTypeIdentifier(); + +}