Mercurial > hg > truffle
changeset 12427:13ae3f7017b5
Merge.
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Tue, 15 Oct 2013 21:28:24 +0200 |
parents | 492c428f6035 (current diff) 737151a29a1f (diff) |
children | 15141192206d |
files | graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameAccessNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameGetNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameSetNode.java |
diffstat | 88 files changed, 2900 insertions(+), 1660 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Tue Oct 15 21:28:24 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.compiler.test.ea; +import java.lang.ref.*; import java.util.concurrent.*; import org.junit.*; @@ -163,6 +164,20 @@ return value; } + public static int testReference1Snippet(Object a) { + SoftReference<Object> softReference = new SoftReference<>(a); + if (softReference.get().hashCode() == 0) { + return 1; + } else { + return 2; + } + } + + @Test + public void testReference1() { + assertEquals(1, processMethod("testReference1Snippet").getNodes().filter(NewInstanceNode.class).count()); + } + @SafeVarargs final void testMaterialize(final String snippet, double expectedProbability, int expectedCount, Class<? extends Node>... invalidNodeClasses) { StructuredGraph result = processMethod(snippet);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Tue Oct 15 21:28:24 2013 +0200 @@ -78,8 +78,7 @@ private static final boolean PROFILE_CONTEXT = false; @Fold - @SuppressWarnings("unused") - private static boolean doProfile(String path) { + private static boolean doProfile() { return Options.ProfileMonitors.getValue(); } @@ -347,7 +346,7 @@ } private static void traceObject(boolean enabled, String action, Object object, boolean enter) { - if (doProfile(action)) { + if (doProfile()) { DynamicCounterNode.counter(action, enter ? "number of monitor enters" : "number of monitor exits", 1, PROFILE_CONTEXT); } if (enabled) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Tue Oct 15 21:28:24 2013 +0200 @@ -112,13 +112,12 @@ } @Fold - @SuppressWarnings("unused") - private static boolean doProfile(String path, String typeContext) { + private static boolean doProfile() { return Options.ProfileAllocations.getValue(); } private static void profileAllocation(String path, long size, String typeContext) { - if (doProfile(path, typeContext)) { + if (doProfile()) { String name = createName(path, typeContext); boolean context = PROFILE_MODE == ProfileMode.AllocatingMethods || PROFILE_MODE == ProfileMode.AllocatedTypesInMethods;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java Tue Oct 15 21:28:24 2013 +0200 @@ -40,12 +40,12 @@ public class UnsafeLoadSnippets implements Snippets { @Snippet - public static Object lowerUnsafeLoad(Object object, long displacement) { + public static Object lowerUnsafeLoad(Object object, long offset) { Object fixedObject = FixedValueAnchorNode.getObject(object); - if (object instanceof java.lang.ref.Reference && referentOffset() == displacement) { - return Word.fromObject(fixedObject).readObject((int) displacement, BarrierType.PRECISE, true); + if (object instanceof java.lang.ref.Reference && referentOffset() == offset) { + return Word.fromObject(fixedObject).readObject((int) offset, BarrierType.PRECISE, true); } else { - return Word.fromObject(fixedObject).readObject((int) displacement, BarrierType.NONE, true); + return Word.fromObject(fixedObject).readObject((int) offset, BarrierType.NONE, true); } }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Oct 15 21:28:24 2013 +0200 @@ -1218,12 +1218,12 @@ return monitorEnter; } - private MonitorExitNode genMonitorExit(ValueNode x) { + private MonitorExitNode genMonitorExit(ValueNode x, ValueNode returnValue) { ValueNode lockedObject = frameState.popLock(); if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) { throw new BailoutException("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject)); } - MonitorExitNode monitorExit = append(new MonitorExitNode(x, frameState.lockDepth())); + MonitorExitNode monitorExit = append(new MonitorExitNode(x, returnValue, frameState.lockDepth())); return monitorExit; } @@ -1619,7 +1619,7 @@ assert frameState.stackSize() == 1 : frameState; ValueNode exception = frameState.apop(); append(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true)); - synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI); + synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI, null); append(new UnwindNode(exception)); } @@ -1628,7 +1628,7 @@ ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind); assert frameState.stackSize() == 0; - synchronizedEpilogue(FrameState.AFTER_BCI); + synchronizedEpilogue(FrameState.AFTER_BCI, x); if (frameState.lockDepth() != 0) { throw new BailoutException("unbalanced monitors"); } @@ -1640,9 +1640,9 @@ append(new ReturnNode(x)); } - private void synchronizedEpilogue(int bci) { + private void synchronizedEpilogue(int bci, ValueNode returnValue) { if (Modifier.isSynchronized(method.getModifiers())) { - MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject); + MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject, returnValue); monitorExit.setStateAfter(frameState.create(bci)); assert !frameState.rethrowException(); } @@ -2002,7 +2002,7 @@ case CHECKCAST : genCheckCast(); break; case INSTANCEOF : genInstanceOf(); break; case MONITORENTER : genMonitorEnter(frameState.apop()); break; - case MONITOREXIT : genMonitorExit(frameState.apop()); break; + case MONITOREXIT : genMonitorExit(frameState.apop(), null); break; case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break; case IFNULL : genIfNull(Condition.EQ); break; case IFNONNULL : genIfNull(Condition.NE); break;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -199,7 +199,7 @@ case Long: return ConstantNode.forLong(value, graph); default: - throw new InternalError("Should not reach here"); + throw GraalInternalError.shouldNotReachHere("unknown kind " + kind); } } @@ -210,7 +210,7 @@ case Double: return ConstantNode.forDouble(value, graph); default: - throw new InternalError("Should not reach here"); + throw GraalInternalError.shouldNotReachHere("unknown kind " + kind); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -82,7 +82,7 @@ @Override public void simplify(SimplifierTool tool) { - if (condition instanceof LogicNegationNode) { + while (condition instanceof LogicNegationNode) { LogicNegationNode negation = (LogicNegationNode) condition; setCondition(negation.getInput()); negated = !negated; @@ -99,8 +99,9 @@ DeoptimizeNode deopt = graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, reason)); deopt.setDeoptimizationState(getDeoptimizationState()); setNext(deopt); + } else { + this.replaceAtUsages(null); } - this.replaceAtUsages(BeginNode.prevBegin(this)); graph().removeFixed(this); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -34,7 +34,7 @@ * A node that changes the stamp of its input based on some condition being true. */ @NodeInfo(nameTemplate = "GuardingPi(!={p#negated}) {p#reason/s}") -public class GuardingPiNode extends FixedWithNextNode implements Lowerable, GuardingNode, Canonicalizable, ValueProxy { +public class GuardingPiNode extends FixedWithNextNode implements Lowerable, Virtualizable, GuardingNode, Canonicalizable, ValueProxy { @Input private ValueNode object; @Input private LogicNode condition; @@ -77,9 +77,6 @@ @Override public void lower(LoweringTool tool) { - if (graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { - throw new GraalInternalError("Cannot create guards in after-guard lowering"); - } GuardingNode guard = tool.createGuard(condition, reason, action, negated); ValueAnchorNode anchor = graph().add(new ValueAnchorNode((ValueNode) guard)); PiNode pi = graph().unique(new PiNode(object, stamp(), (ValueNode) guard)); @@ -88,6 +85,14 @@ } @Override + public void virtualize(VirtualizerTool tool) { + State state = tool.getObjectState(object); + if (state != null && state.getState() == EscapeState.Virtual && ObjectStamp.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) { + tool.replaceWithVirtual(state.getVirtualObject()); + } + } + + @Override public boolean inferStamp() { return updateStamp(stamp().join(object().stamp())); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -462,8 +462,8 @@ List<AbstractEndNode> mergePredecessors = merge.cfgPredecessors().snapshot(); assert phi.valueCount() == merge.forwardEndCount(); - Constant[] xs = constantValues(compare.x(), merge); - Constant[] ys = constantValues(compare.y(), merge); + Constant[] xs = constantValues(compare.x(), merge, false); + Constant[] ys = constantValues(compare.y(), merge, false); if (xs == null || ys == null) { return false; } @@ -607,7 +607,7 @@ * @return null if {@code node} is neither a {@link ConstantNode} nor a {@link PhiNode} whose * input values are all constants */ - private static Constant[] constantValues(ValueNode node, MergeNode merge) { + public static Constant[] constantValues(ValueNode node, MergeNode merge, boolean allowNull) { if (node.isConstant()) { Constant[] result = new Constant[merge.forwardEndCount()]; Arrays.fill(result, node.asConstant()); @@ -620,7 +620,7 @@ Constant[] result = new Constant[merge.forwardEndCount()]; int i = 0; for (ValueNode n : phi.values()) { - if (!n.isConstant()) { + if (!allowNull && !n.isConstant()) { return null; } result[i++] = n.asConstant();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -185,7 +185,7 @@ @Override public void setDeoptimizationState(FrameState f) { - throw new IllegalStateException(); + throw new IllegalStateException("Cannot set deoptimization state " + f + " for invoke " + this); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -35,7 +35,7 @@ * information, i.e., an unsafe cast is removed if the input object has a more precise or equal type * than the type this nodes casts to. */ -public class UnsafeCastNode extends FloatingGuardedNode implements LIRLowerable, GuardingNode, IterableNodeType, Canonicalizable, ValueProxy { +public class UnsafeCastNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, GuardingNode, IterableNodeType, Canonicalizable, ValueProxy { @Input private ValueNode object; @@ -86,6 +86,14 @@ } @Override + public void virtualize(VirtualizerTool tool) { + State state = tool.getObjectState(object); + if (state != null && state.getState() == EscapeState.Virtual && ObjectStamp.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) { + tool.replaceWithVirtual(state.getVirtualObject()); + } + } + + @Override public void generate(LIRGeneratorTool generator) { assert kind() == Kind.Object && object.kind() == Kind.Object; /*
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -63,8 +63,11 @@ if (offsetValue.isConstant()) { long offset = offsetValue.asConstant().asLong(); int entryIndex = state.getVirtualObject().entryIndexForOffset(offset); - if (entryIndex != -1 && state.getVirtualObject().entryKind(entryIndex) == accessKind()) { - tool.replaceWith(state.getEntry(entryIndex)); + if (entryIndex != -1) { + ValueNode entry = state.getEntry(entryIndex); + if (entry.kind() == accessKind() || state.getVirtualObject().entryKind(entryIndex) == accessKind()) { + tool.replaceWith(entry); + } } } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -80,9 +80,12 @@ if (indexValue.isConstant()) { long offset = indexValue.asConstant().asLong(); int entryIndex = state.getVirtualObject().entryIndexForOffset(offset); - if (entryIndex != -1 && state.getVirtualObject().entryKind(entryIndex) == accessKind()) { - tool.setVirtualEntry(state, entryIndex, value()); - tool.delete(); + if (entryIndex != -1) { + ValueNode entry = state.getEntry(entryIndex); + if (entry.kind() == this.accessKind() || state.getVirtualObject().entryKind(entryIndex) == this.accessKind()) { + tool.setVirtualEntry(state, entryIndex, value()); + tool.delete(); + } } } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -91,13 +91,12 @@ * 2: B b = guardingPi(a instanceof B, a, stamp(B, non-null)) * </pre> * - * Note: we use {@link Graph#add} as opposed to {@link Graph#unique} for the new + * Note: we use {@link Graph#addWithoutUnique} as opposed to {@link Graph#unique} for the new * {@link InstanceOfNode} to maintain the invariant checked by * {@code LoweringPhase.checkUsagesAreScheduled()}. */ @Override public void lower(LoweringTool tool) { - InstanceOfNode typeTest = graph().addWithoutUnique(new InstanceOfNode(type, object, profile)); Stamp stamp = StampFactory.declared(type); if (stamp() instanceof ObjectStamp && object().stamp() instanceof ObjectStamp) { stamp = ((ObjectStamp) object().stamp()).castTo((ObjectStamp) stamp); @@ -108,17 +107,20 @@ condition = LogicConstantNode.contradiction(graph()); stamp = StampFactory.declared(type); } else if (ObjectStamp.isObjectNonNull(object)) { - condition = typeTest; + condition = graph().addWithoutUnique(new InstanceOfNode(type, object, profile)); } else { if (profile != null && profile.getNullSeen() == TriState.FALSE) { - FixedGuardNode nullGuard = graph().add(new FixedGuardNode(graph().unique(new IsNullNode(object)), UnreachedCode, DeoptimizationAction.InvalidateReprofile, true)); - graph().addBeforeFixed(this, nullGuard); + FixedGuardNode nullCheck = graph().add(new FixedGuardNode(graph().unique(new IsNullNode(object)), UnreachedCode, InvalidateReprofile, true)); + PiNode nullGuarded = graph().unique(new PiNode(object, object().stamp().join(StampFactory.objectNonNull()), nullCheck)); + InstanceOfNode typeTest = graph().addWithoutUnique(new InstanceOfNode(type, nullGuarded, profile)); + graph().addBeforeFixed(this, nullCheck); condition = typeTest; stamp = stamp.join(StampFactory.objectNonNull()); - nullGuard.lower(tool); + nullCheck.lower(tool); } else { // TODO (ds) replace with probability of null-seen when available double shortCircuitProbability = NOT_FREQUENT_PROBABILITY; + InstanceOfNode typeTest = graph().addWithoutUnique(new InstanceOfNode(type, object, profile)); condition = LogicNode.or(graph().unique(new IsNullNode(object)), typeTest, shortCircuitProbability); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -34,17 +34,24 @@ public final class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Lowerable, IterableNodeType, MonitorExit, MemoryCheckpoint.Single, MonitorReference { private int lockDepth; + @Input private ValueNode escapedReturnValue; /** * Creates a new MonitorExitNode. * * @param object the instruction produces the object value */ - public MonitorExitNode(ValueNode object, int lockDepth) { + public MonitorExitNode(ValueNode object, ValueNode escapedReturnValue, int lockDepth) { super(object); + this.escapedReturnValue = escapedReturnValue; this.lockDepth = lockDepth; } + public void setEscapedReturnValue(ValueNode x) { + updateUsages(escapedReturnValue, x); + this.escapedReturnValue = x; + } + @Override public LocationIdentity getLocationIdentity() { return LocationIdentity.ANY_LOCATION; @@ -65,11 +72,20 @@ @Override public void virtualize(VirtualizerTool tool) { - State state = tool.getObjectState(object()); - if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().hasIdentity()) { - int removedLock = state.removeLock(); - assert removedLock == getLockDepth(); - tool.delete(); + /* + * The last MonitorExitNode of a synchronized method cannot be removed anyway, and we need + * it to materialize the return value. + * + * TODO: replace this with correct handling of AFTER_BCI frame states in the runtime. + */ + if (stateAfter().bci != FrameState.AFTER_BCI) { + setEscapedReturnValue(null); + State state = tool.getObjectState(object()); + if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().hasIdentity()) { + int removedLock = state.removeLock(); + assert removedLock == getLockDepth(); + tool.delete(); + } } } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.java; +import java.lang.ref.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; @@ -48,6 +50,7 @@ */ public NewInstanceNode(ResolvedJavaType type, boolean fillContents) { super(StampFactory.exactNonNull(type)); + assert !type.isArray(); this.instanceClass = type; this.fillContents = fillContents; } @@ -84,8 +87,11 @@ @Override public void virtualize(VirtualizerTool tool) { - if (instanceClass != null) { - assert !instanceClass().isArray(); + /* + * Reference objects can escape into their ReferenceQueue at any safepoint, therefore + * they're excluded from escape analysis. + */ + if (!tool.getMetaAccessProvider().lookupJavaType(Reference.class).isAssignableFrom(instanceClass)) { VirtualInstanceNode virtualObject = new VirtualInstanceNode(instanceClass(), true); ResolvedJavaField[] fields = virtualObject.getFields(); ValueNode[] state = new ValueNode[fields.length];
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -74,7 +74,8 @@ int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1; if (index >= 0 && index < arrayState.getVirtualObject().entryCount()) { ResolvedJavaType componentType = arrayState.getVirtualObject().type().getComponentType(); - if (componentType.isPrimitive() || ObjectStamp.isObjectAlwaysNull(value) || (ObjectStamp.typeOrNull(value) != null && componentType.isAssignableFrom(ObjectStamp.typeOrNull(value)))) { + if (componentType.isPrimitive() || ObjectStamp.isObjectAlwaysNull(value) || componentType.getSuperclass() == null || + (ObjectStamp.typeOrNull(value) != null && componentType.isAssignableFrom(ObjectStamp.typeOrNull(value)))) { tool.setVirtualEntry(arrayState, index, value()); tool.delete(); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java Tue Oct 15 21:28:24 2013 +0200 @@ -22,9 +22,10 @@ */ package com.oracle.graal.nodes.virtual; +import com.oracle.graal.graph.Node.*; import com.oracle.graal.nodes.*; -public abstract class EscapeObjectState extends VirtualState { +public abstract class EscapeObjectState extends VirtualState implements ValueNumberable { @Input private VirtualObjectNode object;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Tue Oct 15 21:28:24 2013 +0200 @@ -24,9 +24,11 @@ import java.util.*; +import com.oracle.graal.api.meta.*; 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.util.*; import com.oracle.graal.phases.*; @@ -45,7 +47,7 @@ */ public class ConvertDeoptimizeToGuardPhase extends Phase { - private static AbstractBeginNode findBeginNode(Node startNode) { + private static AbstractBeginNode findBeginNode(FixedNode startNode) { Node n = startNode; while (true) { if (n instanceof AbstractBeginNode) { @@ -64,16 +66,50 @@ for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.class)) { assert d.isAlive(); - visitDeoptBegin(findBeginNode(d), d, graph); + visitDeoptBegin(BeginNode.prevBegin(d), d.action(), d.reason(), graph); + } + + for (FixedGuardNode fixedGuard : graph.getNodes(FixedGuardNode.class)) { + + AbstractBeginNode pred = BeginNode.prevBegin(fixedGuard); + if (pred instanceof MergeNode) { + MergeNode merge = (MergeNode) pred; + if (fixedGuard.condition() instanceof CompareNode) { + CompareNode compare = (CompareNode) fixedGuard.condition(); + List<AbstractEndNode> mergePredecessors = merge.cfgPredecessors().snapshot(); + + Constant[] xs = IfNode.constantValues(compare.x(), merge, true); + if (xs == null) { + continue; + } + Constant[] ys = IfNode.constantValues(compare.y(), merge, true); + if (ys == null) { + continue; + } + for (int i = 0; i < mergePredecessors.size(); ++i) { + AbstractEndNode mergePredecessor = mergePredecessors.get(i); + if (xs[i] == null) { + continue; + } + if (ys[i] == null) { + continue; + } + if (xs[i].getKind() != Kind.Object && ys[i].getKind() != Kind.Object && + compare.condition().foldCondition(xs[i], ys[i], null, compare.unorderedIsTrue()) == fixedGuard.isNegated()) { + visitDeoptBegin(BeginNode.prevBegin(mergePredecessor), fixedGuard.getAction(), fixedGuard.getReason(), graph); + } + } + } + } } new DeadCodeEliminationPhase().apply(graph); } - private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizeNode deopt, StructuredGraph graph) { + private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph) { if (deoptBegin instanceof MergeNode) { MergeNode mergeNode = (MergeNode) deoptBegin; - Debug.log("Visiting %s followed by %s", mergeNode, deopt); + Debug.log("Visiting %s", mergeNode); List<AbstractBeginNode> begins = new ArrayList<>(); for (AbstractEndNode end : mergeNode.forwardEnds()) { AbstractBeginNode newBeginNode = findBeginNode(end); @@ -82,7 +118,7 @@ } for (AbstractBeginNode begin : begins) { assert !begin.isDeleted(); - visitDeoptBegin(begin, deopt, graph); + visitDeoptBegin(begin, deoptAction, deoptReason, graph); } assert mergeNode.isDeleted(); return; @@ -90,7 +126,7 @@ IfNode ifNode = (IfNode) deoptBegin.predecessor(); AbstractBeginNode otherBegin = ifNode.trueSuccessor(); LogicNode conditionNode = ifNode.condition(); - FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.reason(), deopt.action(), deoptBegin == ifNode.trueSuccessor())); + FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deoptReason, deoptAction, deoptBegin == ifNode.trueSuccessor())); FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor(); AbstractBeginNode survivingSuccessor; if (deoptBegin == ifNode.trueSuccessor()) { @@ -115,7 +151,7 @@ } } } - Debug.log("Converting %s on %-5s branch of %s to guard for remaining branch %s.", deopt, deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, otherBegin); + Debug.log("Converting deopt on %-5s branch of %s to guard for remaining branch %s.", deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, otherBegin); FixedNode next = pred.next(); pred.setNext(guard); guard.setNext(next); @@ -126,8 +162,8 @@ FixedWithNextNode deoptPred = deoptBegin; FixedNode next = deoptPred.next(); - if (next != deopt) { - DeoptimizeNode newDeoptNode = (DeoptimizeNode) deopt.clone(graph); + if (!(next instanceof DeoptimizeNode)) { + DeoptimizeNode newDeoptNode = graph.add(new DeoptimizeNode(deoptAction, deoptReason)); deoptPred.setNext(newDeoptNode); assert deoptPred == newDeoptNode.predecessor(); GraphUtil.killCFG(next);
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Tue Oct 15 21:28:24 2013 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.truffle.test; -import static com.oracle.graal.truffle.TruffleCompilerOptions.*; - import java.util.*; import java.util.concurrent.*; @@ -44,7 +42,6 @@ import com.oracle.graal.phases.util.*; import com.oracle.graal.printer.*; import com.oracle.graal.truffle.*; -import com.oracle.graal.truffle.printer.*; import com.oracle.graal.virtual.phases.ea.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; @@ -136,10 +133,6 @@ new DeadCodeEliminationPhase().apply(resultGraph); new PartialEscapePhase(true, canonicalizer).apply(resultGraph, context); - if (TruffleInlinePrinter.getValue()) { - InlinePrinterProcessor.printTree(); - } - return resultGraph; }
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/StoreLocalTestNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/StoreLocalTestNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -38,11 +38,7 @@ @Override public int execute(VirtualFrame frame) { int value = valueNode.execute(frame); - try { - frame.setInt(slot, value); - } catch (FrameSlotTypeException e) { - throw new IllegalStateException(e); - } + frame.setInt(slot, value); return value; } }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Tue Oct 15 21:28:24 2013 +0200 @@ -36,8 +36,6 @@ */ public final class FrameWithoutBoxing implements VirtualFrame, MaterializedFrame, PackedFrame { - private static final Unsafe unsafe = Unsafe.getUnsafe(); - private final FrameDescriptor descriptor; private final PackedFrame caller; private final Arguments arguments; @@ -87,17 +85,17 @@ } private Object getObjectUnsafe(FrameSlot slot) { - return unsafe.getObject(locals, (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET); + return CompilerDirectives.unsafeGetObject(locals, (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET, true, slot); } @Override public void setObject(FrameSlot slot, Object value) { - verifySetObject(slot); + verifySet(slot, FrameSlotKind.Object); setObjectUnsafe(slot, value); } private void setObjectUnsafe(FrameSlot slot, Object value) { - unsafe.putObject(locals, (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET, value); + CompilerDirectives.unsafePutObject(locals, (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET, value, slot); } @Override @@ -107,17 +105,17 @@ } private byte getByteUnsafe(FrameSlot slot) { - return unsafe.getByte(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + return CompilerDirectives.unsafeGetByte(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot); } @Override - public void setByte(FrameSlot slot, byte value) throws FrameSlotTypeException { + public void setByte(FrameSlot slot, byte value) { verifySet(slot, FrameSlotKind.Byte); setByteUnsafe(slot, value); } private void setByteUnsafe(FrameSlot slot, byte value) { - unsafe.putByte(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + CompilerDirectives.unsafePutByte(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot); } @Override @@ -127,17 +125,17 @@ } private boolean getBooleanUnsafe(FrameSlot slot) { - return unsafe.getBoolean(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + return CompilerDirectives.unsafeGetBoolean(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot); } @Override - public void setBoolean(FrameSlot slot, boolean value) throws FrameSlotTypeException { + public void setBoolean(FrameSlot slot, boolean value) { verifySet(slot, FrameSlotKind.Boolean); setBooleanUnsafe(slot, value); } private void setBooleanUnsafe(FrameSlot slot, boolean value) { - unsafe.putBoolean(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + CompilerDirectives.unsafePutBoolean(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot); } @Override @@ -147,17 +145,17 @@ } private float getFloatUnsafe(FrameSlot slot) { - return unsafe.getFloat(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + return CompilerDirectives.unsafeGetFloat(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot); } @Override - public void setFloat(FrameSlot slot, float value) throws FrameSlotTypeException { + public void setFloat(FrameSlot slot, float value) { verifySet(slot, FrameSlotKind.Float); setFloatUnsafe(slot, value); } private void setFloatUnsafe(FrameSlot slot, float value) { - unsafe.putFloat(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + CompilerDirectives.unsafePutFloat(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot); } @Override @@ -167,17 +165,17 @@ } private long getLongUnsafe(FrameSlot slot) { - return unsafe.getLong(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + return CompilerDirectives.unsafeGetLong(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot); } @Override - public void setLong(FrameSlot slot, long value) throws FrameSlotTypeException { + public void setLong(FrameSlot slot, long value) { verifySet(slot, FrameSlotKind.Long); setLongUnsafe(slot, value); } private void setLongUnsafe(FrameSlot slot, long value) { - unsafe.putLong(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + CompilerDirectives.unsafePutLong(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot); } @Override @@ -187,17 +185,17 @@ } private int getIntUnsafe(FrameSlot slot) { - return unsafe.getInt(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + return CompilerDirectives.unsafeGetInt(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot); } @Override - public void setInt(FrameSlot slot, int value) throws FrameSlotTypeException { + public void setInt(FrameSlot slot, int value) { verifySet(slot, FrameSlotKind.Int); setIntUnsafe(slot, value); } private void setIntUnsafe(FrameSlot slot, int value) { - unsafe.putInt(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + CompilerDirectives.unsafePutInt(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot); } @Override @@ -207,17 +205,17 @@ } private double getDoubleUnsafe(FrameSlot slot) { - return unsafe.getDouble(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + return CompilerDirectives.unsafeGetDouble(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, true, slot); } @Override - public void setDouble(FrameSlot slot, double value) throws FrameSlotTypeException { + public void setDouble(FrameSlot slot, double value) { verifySet(slot, FrameSlotKind.Double); setDoubleUnsafe(slot, value); } private void setDoubleUnsafe(FrameSlot slot, double value) { - unsafe.putDouble(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + CompilerDirectives.unsafePutDouble(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value, slot); } @Override @@ -225,16 +223,7 @@ return this.descriptor; } - private void verifySet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { - FrameSlotKind slotKind = slot.getKind(); - if (slotKind != accessKind) { - CompilerDirectives.transferToInterpreter(); - if (slotKind == FrameSlotKind.Illegal) { - slot.setKind(accessKind); - } else { - throw new FrameSlotTypeException(); - } - } + private void verifySet(FrameSlot slot, FrameSlotKind accessKind) { int slotIndex = slot.getIndex(); if (slotIndex >= tags.length) { CompilerDirectives.transferToInterpreter(); @@ -243,27 +232,14 @@ tags[slotIndex] = (byte) accessKind.ordinal(); } - private void verifySetObject(FrameSlot slot) { - if (slot.getKind() != FrameSlotKind.Object) { - CompilerDirectives.transferToInterpreter(); - slot.setKind(FrameSlotKind.Object); - } - int slotIndex = slot.getIndex(); - if (slotIndex >= tags.length) { - CompilerDirectives.transferToInterpreter(); - resize(); - } - tags[slotIndex] = (byte) FrameSlotKind.Object.ordinal(); - } - private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { int slotIndex = slot.getIndex(); if (slotIndex >= tags.length) { CompilerDirectives.transferToInterpreter(); resize(); } - byte tag = tags[slotIndex]; - if (accessKind == FrameSlotKind.Object ? (tag & 0xfe) != 0 : tag != accessKind.ordinal()) { + byte tag = this.tags[slotIndex]; + if (accessKind == FrameSlotKind.Object ? tag != 0 : tag != accessKind.ordinal()) { CompilerDirectives.transferToInterpreter(); if (slot.getKind() == accessKind || tag == 0) { descriptor.getTypeConversion().updateFrameSlot(this, slot, getValue(slot));
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Tue Oct 15 21:28:24 2013 +0200 @@ -183,6 +183,12 @@ @Override public void nodeReplaced() { replaceCount++; + if (compiledMethod != null) { + if (compiledMethod.isValid()) { + compiledMethod.invalidate(); + } + compiledMethod = null; + } compilationPolicy.nodeReplaced(); }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Tue Oct 15 21:28:24 2013 +0200 @@ -55,8 +55,6 @@ import com.oracle.graal.truffle.nodes.frame.*; import com.oracle.graal.truffle.nodes.frame.NewFrameNode.VirtualOnlyInstanceNode; import com.oracle.graal.truffle.phases.*; -import com.oracle.graal.truffle.printer.*; -import com.oracle.graal.truffle.printer.method.*; import com.oracle.graal.virtual.phases.ea.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; @@ -107,10 +105,6 @@ final StructuredGraph graph = new StructuredGraph(executeHelperMethod); - if (TruffleInlinePrinter.getValue()) { - InlinePrinterProcessor.initialize(); - } - Debug.scope("createGraph", graph, new Runnable() { @Override @@ -140,11 +134,6 @@ new VerifyFrameDoesNotEscapePhase().apply(graph, false); - if (TruffleInlinePrinter.getValue()) { - InlinePrinterProcessor.printTree(); - InlinePrinterProcessor.reset(); - } - if (TraceTruffleCompilationDetails.getValue() && constantReceivers != null) { DebugHistogram histogram = Debug.createHistogram("Expanded Truffle Nodes"); for (Constant c : constantReceivers) { @@ -164,7 +153,7 @@ } // EA frame and clean up. - new PartialEscapePhase(false, canonicalizer).apply(graph, tierContext); + new PartialEscapePhase(true, canonicalizer).apply(graph, tierContext); new VerifyNoIntrinsicsLeftPhase().apply(graph, false); for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.class).snapshot()) { materializeNode.replaceAtUsages(materializeNode.getFrame()); @@ -196,9 +185,6 @@ for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.class)) { InvokeKind kind = methodCallTargetNode.invokeKind(); if (kind == InvokeKind.Static || (kind == InvokeKind.Special && (methodCallTargetNode.receiver().isConstant() || methodCallTargetNode.receiver() instanceof NewFrameNode))) { - if (TruffleInlinePrinter.getValue()) { - InlinePrinterProcessor.addInlining(MethodHolder.getNewTruffleExecuteMethod(methodCallTargetNode)); - } if (TraceTruffleCompilationDetails.getValue() && kind == InvokeKind.Special) { ConstantNode constantNode = (ConstantNode) methodCallTargetNode.arguments().first(); constantReceivers.add(constantNode.asConstant());
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Tue Oct 15 21:28:24 2013 +0200 @@ -60,9 +60,9 @@ @Option(help = "") public static final OptionValue<Integer> TruffleInliningMaxRecursiveDepth = new OptionValue<>(2); @Option(help = "") - public static final OptionValue<Integer> TruffleInliningMaxCallerSize = new OptionValue<>(600); + public static final OptionValue<Integer> TruffleInliningMaxCallerSize = new OptionValue<>(2500); @Option(help = "") - public static final OptionValue<Integer> TruffleInliningMaxCalleeSize = new OptionValue<>(62); + public static final OptionValue<Integer> TruffleInliningMaxCalleeSize = new OptionValue<>(250); @Option(help = "") public static final OptionValue<Integer> TruffleInliningTrivialSize = new OptionValue<>(10); @Option(help = "") @@ -79,8 +79,6 @@ @Option(help = "") public static final OptionValue<Boolean> TraceTruffleCacheDetails = new OptionValue<>(false); @Option(help = "") - public static final OptionValue<Boolean> TruffleInlinePrinter = new OptionValue<>(false); - @Option(help = "") public static final OptionValue<Boolean> TraceTruffleCompilationExceptions = new OptionValue<>(true); @Option(help = "") public static final OptionValue<Boolean> TruffleCompilationExceptionsAreFatal = new OptionValue<>(true);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameAccessNode.java Mon Oct 14 11:24:04 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/* - * 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.graal.truffle.nodes.frame; - -import java.lang.reflect.*; -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.truffle.*; -import com.oracle.graal.truffle.nodes.*; -import com.oracle.graal.truffle.substitutions.*; -import com.oracle.truffle.api.frame.*; - -/** - * Base node class for the intrinsic nodes for read and write access to a Truffle frame. - */ -public abstract class FrameAccessNode extends FixedWithNextNode implements Simplifiable { - - @Input private ValueNode frame; - @Input private ValueNode slot; - protected final ResolvedJavaField field; - protected final Kind slotKind; - - public FrameAccessNode(Stamp stamp, Kind slotKind, ValueNode frame, ValueNode slot, ResolvedJavaField field) { - super(stamp); - this.slotKind = slotKind; - this.frame = frame; - this.slot = slot; - this.field = field; - } - - public ValueNode getFrame() { - return frame; - } - - public ValueNode getSlot() { - return slot; - } - - public Kind getSlotKind() { - return slotKind; - } - - protected int getSlotIndex() { - return getConstantFrameSlot().getIndex(); - } - - public boolean isConstantFrameSlot() { - return slot.isConstant() && !slot.isNullConstant(); - } - - protected FrameSlot getConstantFrameSlot() { - assert isConstantFrameSlot() : slot; - return (FrameSlot) slot.asConstant().asObject(); - } - - protected final void insertDeoptimization(VirtualizerTool tool) { - LogicNode contradiction = LogicConstantNode.contradiction(graph()); - FixedGuardNode fixedGuard = new FixedGuardNode(contradiction, DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile); - tool.addNode(fixedGuard); - } - - @Override - public String toString(Verbosity verbosity) { - if (verbosity == Verbosity.Name) { - return super.toString(verbosity) + getSlotKind().name() + (slot != null && isConstantFrameSlot() ? " " + getConstantFrameSlot() : ""); - } else { - return super.toString(verbosity); - } - } - - protected final ValueNode getSlotOffset(int scale, MetaAccessProvider metaAccess) { - if (isConstantFrameSlot()) { - return ConstantNode.forInt(getSlotIndex() * scale, graph()); - } else { - LoadFieldNode loadFrameSlotIndex = graph().add(new LoadFieldNode(getSlot(), metaAccess.lookupJavaField(getFrameSlotIndexField()))); - graph().addBeforeFixed(this, loadFrameSlotIndex); - return scale == 1 ? loadFrameSlotIndex : IntegerArithmeticNode.mul(loadFrameSlotIndex, ConstantNode.forInt(scale, graph())); - } - } - - private static Field getFrameSlotIndexField() { - try { - return FrameSlotImpl.class.getDeclaredField("index"); - } catch (NoSuchFieldException e) { - throw new RuntimeException(e); - } - } - - protected final boolean isValidAccessKind() { - if (isTagAccess()) { - return true; - } - - return getSlotKind() == getGraalKind(getConstantFrameSlot().getKind()); - } - - protected final boolean isTagAccess() { - return field == FrameWithoutBoxingSubstitutions.TAGS_FIELD; - } - - private static Kind getGraalKind(FrameSlotKind kind) { - switch (kind) { - case Object: - return Kind.Object; - case Long: - return Kind.Long; - case Int: - return Kind.Int; - case Byte: - return Kind.Byte; - case Double: - return Kind.Double; - case Float: - return Kind.Float; - case Boolean: - return Kind.Boolean; - case Illegal: - default: - return Kind.Illegal; - } - } - - @Override - public final void simplify(SimplifierTool tool) { - if (isConstantFrameSlot()) { - if (!isValidAccessKind()) { - tool.deleteBranch(this.next()); - this.replaceAndDelete(graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode))); - } else { - tool.assumptions().record(new AssumptionValidAssumption((OptimizedAssumption) getConstantFrameSlot().getFrameDescriptor().getVersion())); - } - } - } - - @Override - public Map<Object, Object> getDebugProperties(Map<Object, Object> map) { - Map<Object, Object> properties = super.getDebugProperties(map); - if (isTagAccess()) { - properties.put("slotKind", "Tag"); - } - if (isConstantFrameSlot()) { - properties.put("frameSlot", getConstantFrameSlot().toString()); - } - return properties; - } -}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameGetNode.java Mon Oct 14 11:24:04 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -/* - * 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.graal.truffle.nodes.frame; - -import sun.misc.*; - -import com.oracle.graal.api.meta.*; -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.java.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.truffle.*; -import com.oracle.truffle.api.frame.*; - -/** - * Intrinsic node for read access to a Truffle frame. - */ -@NodeInfo(nameTemplate = "FrameGet{p#slotKind/s}{p#frameSlot/s}") -public class FrameGetNode extends FrameAccessNode implements IterableNodeType, Virtualizable, Lowerable { - - public FrameGetNode(Kind kind, ValueNode frame, ValueNode slot, ResolvedJavaField field) { - super(StampFactory.forKind(kind), kind, frame, slot, field); - } - - @Override - public void virtualize(VirtualizerTool tool) { - if (!isConstantFrameSlot()) { - return; - } - assert isValidAccessKind(); - State virtualFrame = tool.getObjectState(getFrame()); - if (virtualFrame == null || virtualFrame.getState() != EscapeState.Virtual) { - return; - } - assert virtualFrame.getVirtualObject().type() == NewFrameNode.FRAME_TYPE : virtualFrame; - VirtualInstanceNode virtualFrameObject = (VirtualInstanceNode) virtualFrame.getVirtualObject(); - int arrayFieldIndex = virtualFrameObject.fieldIndex(field); - State virtualArray = tool.getObjectState(virtualFrame.getEntry(arrayFieldIndex)); - assert virtualArray != null; - ValueNode result = virtualArray.getEntry(getSlotIndex()); - State virtualResult = tool.getObjectState(result); - if (virtualResult != null) { - tool.replaceWithVirtual(virtualResult.getVirtualObject()); - } else { - tool.replaceWithValue(result); - } - } - - @Override - public void lower(LoweringTool tool) { - assert !(getFrame() instanceof NewFrameNode); - StructuredGraph structuredGraph = graph(); - - LoadFieldNode loadFieldNode = graph().add(new LoadFieldNode(getFrame(), field)); - structuredGraph.addBeforeFixed(this, loadFieldNode); - FixedWithNextNode loadNode; - if (isTagAccess()) { - ValueNode slotIndex = getSlotOffset(1, tool.getMetaAccess()); - loadNode = graph().add(new LoadIndexedNode(loadFieldNode, slotIndex, getSlotKind())); - } else if (!getSlotKind().isPrimitive()) { - ValueNode slotIndex = getSlotOffset(1, tool.getMetaAccess()); - loadNode = graph().add(new LoadIndexedNode(loadFieldNode, slotIndex, Kind.Object)); - } else { - ValueNode slotOffset = graph().unique( - new IntegerAddNode(Kind.Long, getSlotOffset(Unsafe.ARRAY_LONG_INDEX_SCALE, tool.getMetaAccess()), ConstantNode.forLong(Unsafe.ARRAY_LONG_BASE_OFFSET, graph()))); - loadNode = graph().add(new UnsafeLoadNode(loadFieldNode, slotOffset, getSlotKind())); - } - structuredGraph.replaceFixedWithFixed(this, loadNode); - loadFieldNode.lower(tool); - ((Lowerable) loadNode).lower(tool); - } - - @NodeIntrinsic - public static native <T> T get(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, @ConstantNodeParameter ResolvedJavaField field); -}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameSetNode.java Mon Oct 14 11:24:04 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/* - * 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.graal.truffle.nodes.frame; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.truffle.*; -import com.oracle.truffle.api.frame.*; - -/** - * Intrinsic node for write access to a Truffle frame. - */ -@NodeInfo(nameTemplate = "FrameSet{p#slotKind/s}{p#frameSlot/s}") -public class FrameSetNode extends FrameAccessNode implements IterableNodeType, Virtualizable, Lowerable { - - @Input private ValueNode value; - - public FrameSetNode(Kind kind, ValueNode frame, ValueNode frameSlot, ValueNode value, ResolvedJavaField field) { - super(StampFactory.forVoid(), kind, frame, frameSlot, field); - this.value = value; - } - - public ValueNode getValue() { - return value; - } - - @Override - public void virtualize(VirtualizerTool tool) { - if (!isConstantFrameSlot()) { - return; - } - assert isValidAccessKind(); - State virtualFrame = tool.getObjectState(getFrame()); - if (virtualFrame == null || virtualFrame.getState() != EscapeState.Virtual) { - return; - } - assert virtualFrame.getVirtualObject().type() == NewFrameNode.FRAME_TYPE : virtualFrame; - VirtualInstanceNode virtualFrameObject = (VirtualInstanceNode) virtualFrame.getVirtualObject(); - int arrayFieldIndex = virtualFrameObject.fieldIndex(field); - State virtualArray = tool.getObjectState(virtualFrame.getEntry(arrayFieldIndex)); - assert virtualArray != null; - ValueNode storedValue = value; - tool.setVirtualEntry(virtualArray, getSlotIndex(), storedValue); - tool.delete(); - } - - @Override - public void lower(LoweringTool tool) { - assert !(getFrame() instanceof NewFrameNode); - StructuredGraph structuredGraph = graph(); - - LoadFieldNode loadFieldNode = graph().add(new LoadFieldNode(getFrame(), field)); - structuredGraph.addBeforeFixed(this, loadFieldNode); - FixedWithNextNode storeNode; - ValueNode slotIndex = getSlotOffset(1, tool.getMetaAccess()); - if (isTagAccess()) { - storeNode = graph().add(new StoreIndexedNode(loadFieldNode, slotIndex, getSlotKind(), value)); - } else if (!getSlotKind().isPrimitive()) { - storeNode = graph().add(new StoreIndexedNode(loadFieldNode, slotIndex, Kind.Object, value)); - } else { - storeNode = graph().add(new StoreIndexedNode(loadFieldNode, slotIndex, Kind.Long, value)); - } - structuredGraph.replaceFixedWithFixed(this, storeNode); - loadFieldNode.lower(tool); - ((Lowerable) storeNode).lower(tool); - } - - @NodeIntrinsic - public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, Object value, @ConstantNodeParameter ResolvedJavaField field); - - @NodeIntrinsic - public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, byte value, @ConstantNodeParameter ResolvedJavaField field); - - @NodeIntrinsic - public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, boolean value, @ConstantNodeParameter ResolvedJavaField field); - - @NodeIntrinsic - public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, int value, @ConstantNodeParameter ResolvedJavaField field); - - @NodeIntrinsic - public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, long value, @ConstantNodeParameter ResolvedJavaField field); - - @NodeIntrinsic - public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, double value, @ConstantNodeParameter ResolvedJavaField field); - - @NodeIntrinsic - public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, float value, @ConstantNodeParameter ResolvedJavaField field); -}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -147,7 +147,7 @@ ResolvedJavaField primitiveLocalsField = findField(frameFields, "primitiveLocals"); ResolvedJavaField tagsField = findField(frameFields, "tags"); - VirtualObjectNode virtualFrame = new VirtualOnlyInstanceNode(frameType, frameFields); + VirtualObjectNode virtualFrame = new VirtualInstanceNode(frameType, frameFields, false); VirtualObjectNode virtualFrameObjectArray = new VirtualArrayNode((ResolvedJavaType) localsField.getType().getComponentType(), frameSize); VirtualObjectNode virtualFramePrimitiveArray = new VirtualArrayNode((ResolvedJavaType) primitiveLocalsField.getType().getComponentType(), frameSize); VirtualObjectNode virtualFrameTagArray = new VirtualArrayNode((ResolvedJavaType) tagsField.getType().getComponentType(), frameSize);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyFrameDoesNotEscapePhase.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyFrameDoesNotEscapePhase.java Tue Oct 15 21:28:24 2013 +0200 @@ -46,12 +46,6 @@ throw GraphUtil.approxSourceException(callTarget, exception); } } - for (FrameAccessNode frameAccess : virtualFrame.usages().filter(FrameAccessNode.class)) { - if (!frameAccess.isConstantFrameSlot()) { - Throwable exception = new VerificationError("Frame slot must be compile-time constant in virtual frame access at: %s frameSlot=%s", frameAccess, frameAccess.getSlot()); - throw GraphUtil.approxSourceException(frameAccess, exception); - } - } } } }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Tue Oct 15 21:28:24 2013 +0200 @@ -29,16 +29,18 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.*; import com.oracle.graal.truffle.nodes.*; import com.oracle.graal.truffle.nodes.typesystem.*; import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; @ClassSubstitution(CompilerDirectives.class) public class CompilerDirectivesSubstitutions { @MethodSubstitution public static void transferToInterpreter() { - DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode); + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.UnreachedCode); } @MethodSubstitution @@ -66,6 +68,11 @@ @MacroSubstitution(macro = UnsafeTypeCastMacroNode.class, isStatic = true) public static native Object unsafeCast(Object value, Class clazz, boolean condition); + @MethodSubstitution + private static Class<? extends MaterializedFrame> getUnsafeFrameType() { + return FrameWithoutBoxing.class; + } + @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) public static native boolean unsafeGetBoolean(Object receiver, long offset, boolean condition, Object locationIdentity);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java Tue Oct 15 21:28:24 2013 +0200 @@ -22,218 +22,15 @@ */ package com.oracle.graal.truffle.substitutions; -import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.nodes.*; import com.oracle.graal.truffle.*; -import com.oracle.graal.truffle.nodes.frame.*; -import com.oracle.truffle.api.frame.*; @ClassSubstitution(FrameWithoutBoxing.class) public class FrameWithoutBoxingSubstitutions { - private static final ResolvedJavaField LOCALS_FIELD; - private static final ResolvedJavaField PRIMITIVELOCALS_FIELD; - public static final ResolvedJavaField TAGS_FIELD; - - static { - try { - MetaAccessProvider runtime = Graal.getRequiredCapability(MetaAccessProvider.class); - LOCALS_FIELD = runtime.lookupJavaField(FrameWithoutBoxing.class.getDeclaredField("locals")); - PRIMITIVELOCALS_FIELD = runtime.lookupJavaField(FrameWithoutBoxing.class.getDeclaredField("primitiveLocals")); - TAGS_FIELD = runtime.lookupJavaField(FrameWithoutBoxing.class.getDeclaredField("tags")); - } catch (NoSuchFieldException e) { - throw new RuntimeException(e); - } - } - @SuppressWarnings("unused") @MethodSubstitution(isStatic = false, forced = true) public static Object pack(FrameWithoutBoxing frame) { return null; } - - @MethodSubstitution(isStatic = false, forced = true) - public static Object getObject(FrameWithoutBoxing frame, FrameSlot slot) { - verifyGet(frame, slot, FrameSlotKind.Object); - return getObjectUnsafe(frame, slot); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static void setObject(FrameWithoutBoxing frame, FrameSlot slot, Object value) { - verifySet(frame, slot, FrameSlotKind.Object); - setObjectUnsafe(frame, slot, value); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static boolean getBoolean(FrameWithoutBoxing frame, FrameSlot slot) { - verifyGet(frame, slot, FrameSlotKind.Boolean); - return getBooleanUnsafe(frame, slot); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static void setBoolean(FrameWithoutBoxing frame, FrameSlot slot, boolean value) { - verifySet(frame, slot, FrameSlotKind.Boolean); - setBooleanUnsafe(frame, slot, value); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static byte getByte(FrameWithoutBoxing frame, FrameSlot slot) { - verifyGet(frame, slot, FrameSlotKind.Byte); - return getByteUnsafe(frame, slot); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static void setByte(FrameWithoutBoxing frame, FrameSlot slot, byte value) { - verifySet(frame, slot, FrameSlotKind.Byte); - setByteUnsafe(frame, slot, value); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static float getFloat(FrameWithoutBoxing frame, FrameSlot slot) { - verifyGet(frame, slot, FrameSlotKind.Float); - return getFloatUnsafe(frame, slot); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static void setFloat(FrameWithoutBoxing frame, FrameSlot slot, float value) { - verifySet(frame, slot, FrameSlotKind.Float); - setFloatUnsafe(frame, slot, value); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static long getLong(FrameWithoutBoxing frame, FrameSlot slot) { - verifyGet(frame, slot, FrameSlotKind.Long); - return getLongUnsafe(frame, slot); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static void setLong(FrameWithoutBoxing frame, FrameSlot slot, long value) { - verifySet(frame, slot, FrameSlotKind.Long); - setLongUnsafe(frame, slot, value); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static int getInt(FrameWithoutBoxing frame, FrameSlot slot) { - verifyGet(frame, slot, FrameSlotKind.Int); - return getIntUnsafe(frame, slot); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static void setInt(FrameWithoutBoxing frame, FrameSlot slot, int value) { - verifySet(frame, slot, FrameSlotKind.Int); - setIntUnsafe(frame, slot, value); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static double getDouble(FrameWithoutBoxing frame, FrameSlot slot) { - verifyGet(frame, slot, FrameSlotKind.Double); - return getDoubleUnsafe(frame, slot); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static void setDouble(FrameWithoutBoxing frame, FrameSlot slot, double value) { - verifySet(frame, slot, FrameSlotKind.Double); - setDoubleUnsafe(frame, slot, value); - } - - @MethodSubstitution(isStatic = false) - public static Object getObjectUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { - return FrameGetNode.get(Kind.Object, frame, slot, LOCALS_FIELD); - } - - @MethodSubstitution(isStatic = false) - public static void setObjectUnsafe(FrameWithoutBoxing frame, FrameSlot slot, Object value) { - FrameSetNode.set(Kind.Object, frame, slot, value, LOCALS_FIELD); - } - - @MethodSubstitution(isStatic = false) - public static boolean getBooleanUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { - return FrameGetNode.get(Kind.Boolean, frame, slot, PRIMITIVELOCALS_FIELD); - } - - @MethodSubstitution(isStatic = false) - public static void setBooleanUnsafe(FrameWithoutBoxing frame, FrameSlot slot, boolean value) { - FrameSetNode.set(Kind.Boolean, frame, slot, value, PRIMITIVELOCALS_FIELD); - } - - @MethodSubstitution(isStatic = false) - public static byte getByteUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { - return FrameGetNode.get(Kind.Byte, frame, slot, PRIMITIVELOCALS_FIELD); - } - - @MethodSubstitution(isStatic = false) - public static void setByteUnsafe(FrameWithoutBoxing frame, FrameSlot slot, byte value) { - FrameSetNode.set(Kind.Byte, frame, slot, value, PRIMITIVELOCALS_FIELD); - } - - @MethodSubstitution(isStatic = false) - public static int getIntUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { - return FrameGetNode.get(Kind.Int, frame, slot, PRIMITIVELOCALS_FIELD); - } - - @MethodSubstitution(isStatic = false) - public static void setIntUnsafe(FrameWithoutBoxing frame, FrameSlot slot, int value) { - FrameSetNode.set(Kind.Int, frame, slot, value, PRIMITIVELOCALS_FIELD); - } - - @MethodSubstitution(isStatic = false) - public static long getLongUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { - return FrameGetNode.get(Kind.Long, frame, slot, PRIMITIVELOCALS_FIELD); - } - - @MethodSubstitution(isStatic = false) - public static void setLongUnsafe(FrameWithoutBoxing frame, FrameSlot slot, long value) { - FrameSetNode.set(Kind.Long, frame, slot, value, PRIMITIVELOCALS_FIELD); - } - - @MethodSubstitution(isStatic = false) - public static double getDoubleUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { - return FrameGetNode.get(Kind.Double, frame, slot, PRIMITIVELOCALS_FIELD); - } - - @MethodSubstitution(isStatic = false) - public static void setDoubleUnsafe(FrameWithoutBoxing frame, FrameSlot slot, double value) { - FrameSetNode.set(Kind.Double, frame, slot, value, PRIMITIVELOCALS_FIELD); - } - - @MethodSubstitution(isStatic = false) - public static float getFloatUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { - return FrameGetNode.get(Kind.Float, frame, slot, PRIMITIVELOCALS_FIELD); - } - - @MethodSubstitution(isStatic = false) - public static void setFloatUnsafe(FrameWithoutBoxing frame, FrameSlot slot, float value) { - FrameSetNode.set(Kind.Float, frame, slot, value, PRIMITIVELOCALS_FIELD); - } - - private static void verifySet(FrameWithoutBoxing frame, FrameSlot slot, FrameSlotKind accessType) { - setTag(frame, slot, (byte) accessType.ordinal()); - } - - private static void verifyGet(FrameWithoutBoxing frame, FrameSlot slot, FrameSlotKind accessType) { - byte tag = getTag(frame, slot); - if (accessType == FrameSlotKind.Object ? (tag & 0xfe) != 0 : tag != (byte) accessType.ordinal()) { - DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode); - } - } - - private static byte getTag(FrameWithoutBoxing frame, FrameSlot slot) { - return FrameGetNode.get(Kind.Byte, frame, slot, TAGS_FIELD); - } - - private static void setTag(FrameWithoutBoxing frame, FrameSlot slot, byte tag) { - FrameSetNode.set(Kind.Byte, frame, slot, tag, TAGS_FIELD); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static MaterializedFrame materialize(FrameWithoutBoxing frame) { - return MaterializeFrameNode.materialize(frame); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static boolean isInitialized(FrameWithoutBoxing frame, FrameSlot slot) { - return getTag(frame, slot) != 0; - } }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java Tue Oct 15 21:28:24 2013 +0200 @@ -44,7 +44,7 @@ @Override public MaterializedObjectState duplicateWithVirtualState() { - return graph().addWithoutUnique(new MaterializedObjectState(object(), materializedValue)); + return graph().unique(new MaterializedObjectState(object(), materializedValue)); } @Override
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java Tue Oct 15 21:28:24 2013 +0200 @@ -53,7 +53,7 @@ @Override public VirtualObjectState duplicateWithVirtualState() { - return graph().addWithoutUnique(new VirtualObjectState(object(), fieldValues)); + return graph().unique(new VirtualObjectState(object(), fieldValues)); } @Override
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Tue Oct 15 21:28:24 2013 +0200 @@ -178,7 +178,7 @@ stateAfter.virtualObjectMappings().remove(i); } } - stateAfter.addVirtualObjectMapping(graph.addWithoutUnique(state)); + stateAfter.addVirtualObjectMapping(graph.unique(state)); } @Override
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Tue Oct 15 21:28:24 2013 +0200 @@ -111,85 +111,6 @@ return !(node instanceof CommitAllocationNode || node instanceof AllocatedObjectNode); } if (isMarked) { - if (node instanceof NodeWithState) { - NodeWithState nodeWithState = (NodeWithState) node; - FrameState stateAfter = nodeWithState.getState(); - if (stateAfter != null) { - if (stateAfter.usages().count() > 1) { - if (nodeWithState instanceof StateSplit) { - StateSplit split = (StateSplit) nodeWithState; - stateAfter = (FrameState) stateAfter.copyWithInputs(); - split.setStateAfter(stateAfter); - } else { - throw GraalInternalError.shouldNotReachHere(); - } - } - final HashSet<ObjectState> virtual = new HashSet<>(); - stateAfter.applyToNonVirtual(new NodeClosure<ValueNode>() { - - @Override - public void apply(Node usage, ValueNode value) { - ObjectState valueObj = getObjectState(state, value); - if (valueObj != null) { - virtual.add(valueObj); - effects.replaceFirstInput(usage, value, valueObj.virtual); - } else if (value instanceof VirtualObjectNode) { - ObjectState virtualObj = null; - for (ObjectState obj : state.getStates()) { - if (value == obj.virtual) { - virtualObj = obj; - break; - } - } - if (virtualObj != null) { - virtual.add(virtualObj); - } - } - } - }); - for (ObjectState obj : state.getStates()) { - if (obj.isVirtual() && obj.hasLocks()) { - virtual.add(obj); - } - } - - ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual); - while (!queue.isEmpty()) { - ObjectState obj = queue.removeLast(); - if (obj.isVirtual()) { - for (ValueNode field : obj.getEntries()) { - if (field instanceof VirtualObjectNode) { - ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field); - if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) { - virtual.add(fieldObj); - queue.addLast(fieldObj); - } - } - } - } - } - for (ObjectState obj : virtual) { - EscapeObjectState v; - if (obj.isVirtual()) { - ValueNode[] fieldState = obj.getEntries().clone(); - for (int i = 0; i < fieldState.length; i++) { - ObjectState valueObj = getObjectState(state, fieldState[i]); - if (valueObj != null) { - if (valueObj.isVirtual()) { - fieldState[i] = valueObj.virtual; - } else { - fieldState[i] = valueObj.getMaterializedValue(); - } - } - } - v = new VirtualObjectState(obj.virtual, fieldState); - } else { - v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue()); - } - effects.addVirtualMapping(stateAfter, v); - } - } - } for (ValueNode input : node.inputs().filter(ValueNode.class)) { ObjectState obj = getObjectState(state, input); if (obj != null) { @@ -201,10 +122,92 @@ replaceWithMaterialized(input, node, insertBefore, state, obj, effects, METRIC_MATERIALIZATIONS_UNHANDLED); } } + if (node instanceof NodeWithState) { + processNodeWithState((NodeWithState) node, state, effects); + } } return false; } + private void processNodeWithState(NodeWithState nodeWithState, final BlockT state, final GraphEffectList effects) { + FrameState stateAfter = nodeWithState.getState(); + if (stateAfter != null) { + if (stateAfter.usages().count() > 1) { + if (nodeWithState instanceof StateSplit) { + StateSplit split = (StateSplit) nodeWithState; + stateAfter = (FrameState) stateAfter.copyWithInputs(); + split.setStateAfter(stateAfter); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } + final HashSet<ObjectState> virtual = new HashSet<>(); + stateAfter.applyToNonVirtual(new NodeClosure<ValueNode>() { + + @Override + public void apply(Node usage, ValueNode value) { + ObjectState valueObj = getObjectState(state, value); + if (valueObj != null) { + virtual.add(valueObj); + effects.replaceFirstInput(usage, value, valueObj.virtual); + } else if (value instanceof VirtualObjectNode) { + ObjectState virtualObj = null; + for (ObjectState obj : state.getStates()) { + if (value == obj.virtual) { + virtualObj = obj; + break; + } + } + if (virtualObj != null) { + virtual.add(virtualObj); + } + } + } + }); + for (ObjectState obj : state.getStates()) { + if (obj.isVirtual() && obj.hasLocks()) { + virtual.add(obj); + } + } + + ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual); + while (!queue.isEmpty()) { + ObjectState obj = queue.removeLast(); + if (obj.isVirtual()) { + for (ValueNode field : obj.getEntries()) { + if (field instanceof VirtualObjectNode) { + ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field); + if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) { + virtual.add(fieldObj); + queue.addLast(fieldObj); + } + } + } + } + } + for (ObjectState obj : virtual) { + EscapeObjectState v; + if (obj.isVirtual()) { + ValueNode[] fieldState = obj.getEntries().clone(); + for (int i = 0; i < fieldState.length; i++) { + ObjectState valueObj = getObjectState(state, fieldState[i]); + if (valueObj != null) { + if (valueObj.isVirtual()) { + fieldState[i] = valueObj.virtual; + } else { + fieldState[i] = valueObj.getMaterializedValue(); + } + } + } + v = new VirtualObjectState(obj.virtual, fieldState); + } else { + v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue()); + } + effects.addVirtualMapping(stateAfter, v); + } + } + } + private void ensureMaterialized(BlockT state, ObjectState obj, FixedNode materializeBefore, GraphEffectList effects, DebugMetric metric) { assert obj != null; if (obj.getState() == EscapeState.Virtual) {
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java Tue Oct 15 21:28:24 2013 +0200 @@ -26,6 +26,8 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast0NodeFactory; +import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast1NodeFactory; +import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast2NodeFactory; import com.oracle.truffle.api.dsl.test.NodeContainerTest.Str; import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; @@ -55,12 +57,12 @@ public abstract Object executeEvaluated(VirtualFrame frame, Object value2); @Specialization(order = 1) - public String op1(String value) throws RuntimeException { + public String op1(String value) { return value; } @Specialization(order = 2) - public boolean op1(boolean value) throws RuntimeException { + public boolean op1(boolean value) { return value; } @@ -77,8 +79,79 @@ Assert.assertEquals(true, root.getNode().executeEvaluated(null, true)); } - // TODO assert implicit casts only in one direction + @TypeSystemReference(ImplicitCast0Types.class) + @NodeChild(value = "operand", type = ImplicitCast1Node.class) + // TODO temporary workaround + abstract static class ImplicitCast1Node extends ValueNode { + + public abstract Object executeEvaluated(VirtualFrame frame, Object operand); + + @Specialization(order = 0) + public String op0(String value) { + return value; + } + + @Specialization(order = 1, rewriteOn = RuntimeException.class) + public boolean op1(@SuppressWarnings("unused") boolean value) throws RuntimeException { + throw new RuntimeException(); + } + + @Specialization(order = 2) + public boolean op2(boolean value) { + return value; + } + + } + + @Test + public void testImplicitCast1() { + ImplicitCast1Node node = ImplicitCast1NodeFactory.create(null); + TestRootNode<ImplicitCast1Node> root = new TestRootNode<>(node); + Assert.assertEquals("2", root.getNode().executeEvaluated(null, "2")); + Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1)); + Assert.assertEquals("1", root.getNode().executeEvaluated(null, "1")); + Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1)); + Assert.assertEquals(true, root.getNode().executeEvaluated(null, true)); + } - // test example that covers the most cases + @TypeSystemReference(ImplicitCast0Types.class) + @NodeChildren({@NodeChild(value = "operand0", type = ImplicitCast2Node.class), @NodeChild(value = "operand1", type = ImplicitCast2Node.class, executeWith = "operand0")}) + // TODO temporary workaround + abstract static class ImplicitCast2Node extends ValueNode { + + @Specialization(order = 0) + public String op0(String v0, String v1) { + return v0 + v1; + } + + @SuppressWarnings("unused") + @Specialization(order = 1, rewriteOn = RuntimeException.class) + public boolean op1(boolean v0, boolean v1) throws RuntimeException { + throw new RuntimeException(); + } + + @Specialization(order = 2) + public boolean op2(boolean v0, boolean v1) { + return v0 && v1; + } + + public abstract Object executeEvaluated(VirtualFrame frame, Object v1); + + public abstract Object executeEvaluated(VirtualFrame frame, Object v1, Object v2); + + public abstract Object executeEvaluated(VirtualFrame frame, boolean v1, boolean v2); + + } + + @Test + public void testImplicitCast2() { + ImplicitCast2Node node = ImplicitCast2NodeFactory.create(null, null); + TestRootNode<ImplicitCast2Node> root = new TestRootNode<>(node); + Assert.assertEquals("42", root.getNode().executeEvaluated(null, "4", "2")); + Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1, 1)); + Assert.assertEquals("42", root.getNode().executeEvaluated(null, "4", "2")); + Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1, 1)); + Assert.assertEquals(true, root.getNode().executeEvaluated(null, true, true)); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SlowPathTest.java Tue Oct 15 21:28:24 2013 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2012, 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.truffle.api.dsl.test; + +import org.junit.*; + +import com.oracle.truffle.api.CompilerDirectives.SlowPath; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.SlowPathTestFactory.SlowPathOnGeneric0Factory; +import com.oracle.truffle.api.dsl.test.SlowPathTestFactory.SlowPathOnGeneric1Factory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** Tests the generated placement of {@link SlowPath} in generated methods. */ +public class SlowPathTest { + + @Test + public void testSlowPathOnGeneric0() throws NoSuchMethodException, SecurityException { + Node node = SlowPathOnGeneric0Factory.create(null); + Assert.assertNull(node.getClass().getSuperclass().getDeclaredMethod("executeGeneric0", VirtualFrame.class, Object.class).getAnnotation(SlowPath.class)); + } + + @NodeChild + abstract static class SlowPathOnGeneric0 extends ValueNode { + + @Specialization + @SuppressWarnings("unused") + Object doObject0(VirtualFrame frame, int value0) { + throw new AssertionError(); + } + + } + + @Test + public void testSlowPathOnGeneric1() throws NoSuchMethodException, SecurityException { + Node node = SlowPathOnGeneric1Factory.create(null); + Assert.assertNotNull(node.getClass().getSuperclass().getDeclaredMethod("executeGeneric0", Object.class).getAnnotation(SlowPath.class)); + } + + @NodeChild + abstract static class SlowPathOnGeneric1 extends ValueNode { + + @Specialization + @SuppressWarnings("unused") + Object doObject0(int value0) { + throw new AssertionError(); + } + + } + +}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java Tue Oct 15 21:28:24 2013 +0200 @@ -37,7 +37,8 @@ /** * Tests execution counts of guards. While we do not make guarantees for guard invocation except for - * their execution order our implementation reduces the calls to guards as much as possible. + * their execution order our implementation reduces the calls to guards as much as possible for the + * generic case. */ public class SpecializationGroupingTest { @@ -47,7 +48,7 @@ MockAssumption a2 = new MockAssumption(false); MockAssumption a3 = new MockAssumption(true); - TestRootNode<TestGrouping> root = TestHelper.createRoot(TestGroupingFactory.getInstance(), a1, a2, a3); + TestRootNode<TestGrouping> root = TestHelper.createGenericRoot(TestGroupingFactory.getInstance(), a1, a2, a3); SimpleTypes.intCast = 0; SimpleTypes.intCheck = 0; @@ -71,16 +72,16 @@ Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21)); Assert.assertEquals(2, TestGrouping.true1); - Assert.assertEquals(1, TestGrouping.false1); + Assert.assertEquals(2, TestGrouping.false1); Assert.assertEquals(2, TestGrouping.true2); Assert.assertEquals(2, TestGrouping.false2); Assert.assertEquals(2, TestGrouping.true3); Assert.assertEquals(2, a1.checked); - Assert.assertEquals(1, a2.checked); + Assert.assertEquals(2, a2.checked); Assert.assertEquals(2, a3.checked); - Assert.assertEquals(2, SimpleTypes.intCheck); - Assert.assertEquals(2, SimpleTypes.intCast); + Assert.assertEquals(4, SimpleTypes.intCheck); + Assert.assertEquals(4, SimpleTypes.intCast); }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Tue Oct 15 21:28:24 2013 +0200 @@ -61,10 +61,18 @@ return factory.createNode(argumentList.toArray(new Object[argumentList.size()])); } + static <E extends ValueNode> E createGenericNode(NodeFactory<E> factory, Object... constants) { + return factory.createNodeGeneric(createNode(factory, constants)); + } + static <E extends ValueNode> TestRootNode<E> createRoot(NodeFactory<E> factory, Object... constants) { return new TestRootNode<>(createNode(factory, constants)); } + static <E extends ValueNode> TestRootNode<E> createGenericRoot(NodeFactory<E> factory, Object... constants) { + return new TestRootNode<>(createGenericNode(factory, constants)); + } + static CallTarget createCallTarget(ValueNode node) { return createCallTarget(new TestRootNode<>(node)); }
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java Tue Oct 15 21:28:24 2013 +0200 @@ -115,14 +115,11 @@ Object execute(VirtualFrame frame) { Object o = value.execute(frame); if (o instanceof Integer) { - try { - frame.setInt(slot, (Integer) o); - } catch (FrameSlotTypeException e) { - // fall through - } + frame.setInt(slot, (Integer) o); + } else { + frame.setObject(slot, o); + this.replace(new ObjectAssignLocal(slot, value)); } - frame.setObject(slot, o); - this.replace(new ObjectAssignLocal(slot, value)); return null; } }
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java Tue Oct 15 21:28:24 2013 +0200 @@ -114,11 +114,7 @@ @Override int execute(VirtualFrame frame) { - try { - frame.setInt(slot, 42); - } catch (FrameSlotTypeException e) { - throw new IllegalStateException(e); - } + frame.setInt(slot, 42); return 0; } }
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java Tue Oct 15 21:28:24 2013 +0200 @@ -122,12 +122,7 @@ Object execute(VirtualFrame frame) { try { int result = value.executeInt(frame); - try { - frame.setInt(slot, result); - } catch (FrameSlotTypeException e) { - frame.setObject(slot, result); - replace(new ObjectAssignLocal(slot, value)); - } + frame.setInt(slot, result); } catch (UnexpectedResultException e) { frame.setObject(slot, e.getResult()); replace(new ObjectAssignLocal(slot, value));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderDeserializerTest.java Tue Oct 15 21:28:24 2013 +0200 @@ -0,0 +1,184 @@ +/* + * Copyright (c) 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.truffle.api.test.nodes.serial; + +import java.nio.*; +import java.util.*; + +import org.junit.*; + +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.serial.*; +import com.oracle.truffle.api.test.nodes.serial.TestNodes.EmptyNode; +import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithArray; +import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithFields; +import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithOneChild; +import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithThreeChilds; +import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithTwoArray; +import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithTwoChilds; +import com.oracle.truffle.api.test.nodes.serial.TestNodes.StringNode; + +public class PostOrderDeserializerTest { + + private PostOrderDeserializer d; + private TestSerializerConstantPool cp; + + @Before + public void setUp() { + cp = new TestSerializerConstantPool(); + d = new PostOrderDeserializer(cp); + } + + @After + public void tearDown() { + d = null; + cp = null; + } + + private Node deserialize(byte[] bytes) { + return d.deserialize(bytes, Node.class); + } + + @Test + public void testNull() { + createCP(); + Node ast = deserialize(createBytes(VariableLengthIntBuffer.NULL)); + Assert.assertNull(ast); + } + + @Test + public void testSingleNode() { + createCP(EmptyNode.class); + Node expectedAst = new EmptyNode(); + Node ast = deserialize(createBytes(0)); + assertAST(expectedAst, ast); + } + + @Test + public void testThreeChilds() { + createCP(EmptyNode.class, NodeWithThreeChilds.class); + Node expectedAst = new NodeWithThreeChilds(new EmptyNode(), null, new EmptyNode()); + Node ast = deserialize(createBytes(0, VariableLengthIntBuffer.NULL, 0, 1)); + assertAST(expectedAst, ast); + } + + @Test + public void testFields() { + createCP(NodeWithFields.class, "test", Integer.MIN_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, Double.MIN_VALUE, Double.MAX_VALUE, + (int) Character.MIN_VALUE, (int) Character.MAX_VALUE, (int) Short.MIN_VALUE, (int) Short.MAX_VALUE, (int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE, 1); + NodeWithFields expectedAst = new NodeWithFields("test", Integer.MIN_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, Double.MIN_VALUE, + Double.MAX_VALUE, Character.MIN_VALUE, Character.MAX_VALUE, Short.MIN_VALUE, Short.MAX_VALUE, Byte.MIN_VALUE, Byte.MAX_VALUE, Boolean.TRUE, Boolean.FALSE); + Node ast = deserialize(createBytes(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 10)); + assertAST(expectedAst, ast); + } + + @Test + public void testFieldsNull() { + createCP(NodeWithFields.class, "test", 0, 0L, 0.0F, 0.0D); + NodeWithFields expectedAst = new NodeWithFields("test", 0, null, 0L, null, 0f, null, 0d, null, (char) 0, null, (short) 0, null, (byte) 0, null, false, null); + int nil = VariableLengthIntBuffer.NULL; + Node ast = deserialize(createBytes(0, 1, 2, nil, 3, nil, 4, nil, 5, nil, 2, nil, 2, nil, 2, nil, 2, nil)); + assertAST(expectedAst, ast); + } + + @Test + public void testNullChilds() { + createCP(Node[].class, NodeWithArray.class); + Node expectedAst = new NodeWithArray(null); + Node ast = deserialize(createBytes(0, VariableLengthIntBuffer.NULL, 1)); + assertAST(expectedAst, ast); + } + + @Test + public void testNChilds() { + Node expectedAst = new NodeWithArray(new Node[]{new EmptyNode(), new NodeWithArray(new Node[]{new EmptyNode(), new EmptyNode(), new EmptyNode()}), new EmptyNode(), new EmptyNode()}); + createCP(Node[].class, 4, EmptyNode.class, 3, NodeWithArray.class); + Node ast = deserialize(createBytes(0, 1, 2, 0, 3, 2, 2, 2, 4, 2, 2, 4)); + + assertAST(expectedAst, ast); + } + + @Test + public void test2xNChilds() { + Node expectedAst = new NodeWithTwoArray(new Node[]{new StringNode("a0"), new StringNode("a1")}, new Node[]{new StringNode("b0"), new StringNode("b1"), new StringNode("b2")}); + createCP(Node[].class, 2, StringNode.class, "a0", "a1", 3, "b0", "b1", "b2", NodeWithTwoArray.class); + Node ast = deserialize(createBytes(0, 1, 2, 3, 2, 4, 0, 5, 2, 6, 2, 7, 2, 8, 9)); + + assertAST(expectedAst, ast); + } + + @Test + public void testBug0() { + Node expectedAst = new NodeWithArray(new Node[]{new NodeWithOneChild(new EmptyNode())}); + + createCP(Node[].class, 1, EmptyNode.class, NodeWithOneChild.class, NodeWithArray.class); + Node ast = deserialize(createBytes(0, 1, 2, 3, 4)); + assertAST(expectedAst, ast); + } + + @Test + public void testBug1() { + Node expectedAst = new NodeWithArray(new Node[]{new NodeWithTwoChilds(new EmptyNode(), new EmptyNode())}); + + createCP(Node[].class, 1, EmptyNode.class, NodeWithTwoChilds.class, NodeWithArray.class); + Node ast = deserialize(createBytes(0, 1, 2, 2, 3, 4)); + assertAST(expectedAst, ast); + } + + private static void assertAST(Node expectedAst, Node actualAst) { + if (expectedAst == null) { + Assert.assertNull(actualAst); + return; + } + + Assert.assertNotNull(actualAst); + // fields are asserted using the corresponding equals implementation + Assert.assertEquals(expectedAst, actualAst); + + Iterable<Node> expectedChildIterator = expectedAst.getChildren(); + Iterator<Node> actualChildIterator = actualAst.getChildren().iterator(); + for (Node node : expectedChildIterator) { + Assert.assertTrue(actualChildIterator.hasNext()); + assertAST(node, actualChildIterator.next()); + } + Assert.assertFalse(actualChildIterator.hasNext()); + } + + private static byte[] createBytes(int... refs) { + VariableLengthIntBuffer buf = new VariableLengthIntBuffer(ByteBuffer.allocate(512)); + for (int i = 0; i < refs.length; i++) { + buf.put(refs[i]); + } + return buf.getBytes(); + } + + private void createCP(Object... cpData) { + for (int i = 0; i < cpData.length; i++) { + Object object = cpData[i]; + + cp.putObject(object.getClass(), object); + + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderSerializerTest.java Tue Oct 15 21:28:24 2013 +0200 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 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.truffle.api.test.nodes.serial; + +import org.junit.*; + +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.serial.*; +import com.oracle.truffle.api.test.nodes.serial.TestNodes.EmptyNode; +import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithArray; +import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithFields; +import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithThreeChilds; +import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithTwoArray; +import com.oracle.truffle.api.test.nodes.serial.TestNodes.StringNode; + +public class PostOrderSerializerTest { + + private PostOrderSerializer s; + private TestSerializerConstantPool cp; + + @Before + public void setUp() { + cp = new TestSerializerConstantPool(); + s = new PostOrderSerializer(cp); + } + + @After + public void tearDown() { + cp = null; + s = null; + } + + @Test + public void testNull() { + Node ast = null; + assertBytes(s.serialize(ast), VariableLengthIntBuffer.NULL); + assertCP(); + } + + @Test + public void testSingleEmptyNode() { + Node ast = new EmptyNode(); + assertBytes(s.serialize(ast), 0); + assertCP(EmptyNode.class); + } + + @Test + public void testThreeChilds() { + Node ast = new NodeWithThreeChilds(new EmptyNode(), null, new EmptyNode()); + assertBytes(s.serialize(ast), 0, VariableLengthIntBuffer.NULL, 0, 1); + assertCP(EmptyNode.class, NodeWithThreeChilds.class); + } + + @Test + public void testFields() { + NodeWithFields ast = new NodeWithFields("test", Integer.MIN_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, Double.MIN_VALUE, Double.MAX_VALUE, + Character.MIN_VALUE, Character.MAX_VALUE, Short.MIN_VALUE, Short.MAX_VALUE, Byte.MIN_VALUE, Byte.MAX_VALUE, Boolean.TRUE, Boolean.FALSE); + assertBytes(s.serialize(ast), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 10); + assertCP(NodeWithFields.class, "test", Integer.MIN_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, Double.MIN_VALUE, Double.MAX_VALUE, + (int) Character.MIN_VALUE, (int) Character.MAX_VALUE, (int) Short.MIN_VALUE, (int) Short.MAX_VALUE, (int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE, 1); + } + + @Test + public void testFieldsNull() { + NodeWithFields ast = new NodeWithFields("test", 0, null, 0L, null, 0f, null, 0d, null, (char) 0, null, (short) 0, null, (byte) 0, null, false, null); + int nil = VariableLengthIntBuffer.NULL; + assertBytes(s.serialize(ast), 0, 1, 2, nil, 3, nil, 4, nil, 5, nil, 2, nil, 2, nil, 2, nil, 2, nil); + assertCP(NodeWithFields.class, "test", 0, 0L, 0.0F, 0.0D); + } + + @Test + public void testNChilds() { + Node ast = new NodeWithArray(new Node[]{new EmptyNode(), new NodeWithArray(new Node[]{new EmptyNode(), new EmptyNode(), new EmptyNode()}), new EmptyNode(), new EmptyNode()}); + assertBytes(s.serialize(ast), 0, 1, 2, 0, 3, 2, 2, 2, 4, 2, 2, 4); + assertCP(Node[].class, 4, EmptyNode.class, 3, NodeWithArray.class); + } + + @Test + public void testNullChilds() { + Node ast = new NodeWithArray(null); + assertBytes(s.serialize(ast), 0, VariableLengthIntBuffer.NULL, 1); + assertCP(Node[].class, NodeWithArray.class); + } + + @Test + public void test2xNChilds() { + Node ast = new NodeWithTwoArray(new Node[]{new StringNode("a0"), new StringNode("a1")}, new Node[]{new StringNode("b0"), new StringNode("b1"), new StringNode("b2")}); + assertBytes(s.serialize(ast), 0, 1, 2, 3, 2, 4, 0, 5, 2, 6, 2, 7, 2, 8, 9); + assertCP(Node[].class, 2, StringNode.class, "a0", "a1", 3, "b0", "b1", "b2", NodeWithTwoArray.class); + } + + private static void assertBytes(byte[] actualBytes, int... expectedIndexes) { + VariableLengthIntBuffer buf = new VariableLengthIntBuffer(actualBytes); + for (int i = 0; i < expectedIndexes.length; i++) { + Assert.assertTrue("Unexpected EOF " + i, buf.hasRemaining()); + Assert.assertEquals("Index at pos " + i + ".", expectedIndexes[i], buf.get()); + } + Assert.assertFalse(buf.hasRemaining()); + } + + private void assertCP(Object... object) { + for (int i = 0; i < object.length; i++) { + Object cpvalue = object[i]; + Assert.assertNotNull("CP at index " + i, cpvalue); + Assert.assertEquals("CP at index " + i, cpvalue, cp.getObject(cpvalue.getClass(), i)); + } + Assert.assertEquals(object.length, cp.getIndex()); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestNodes.java Tue Oct 15 21:28:24 2013 +0200 @@ -0,0 +1,221 @@ +/* + * Copyright (c) 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.truffle.api.test.nodes.serial; + +import java.util.*; + +import com.oracle.truffle.api.nodes.*; + +final class TestNodes { + + private TestNodes() { + } + + static class StringNode extends Node { + + private final String name; + + public StringNode(String name) { + this.name = name; + } + + @Override + public int hashCode() { + return Objects.hash(name); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } else if (obj.getClass() != getClass()) { + return false; + } else if ((((Node) obj).getParent() != null) && !((Node) obj).getParent().equals(getParent())) { + return false; + } else if (!Objects.equals(name, ((StringNode) obj).name)) { + return false; + } + return true; + } + } + + static class EmptyNode extends Node { + + @Override + public int hashCode() { + return super.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } else if (obj.getClass() != getClass()) { + return false; + } else if ((((Node) obj).getParent() != null) && !((Node) obj).getParent().equals(getParent())) { + return false; + } + return true; + } + } + + static class NodeWithOneChild extends EmptyNode { + + @Child Node child; + + public NodeWithOneChild(Node child) { + this.child = adoptChild(child); + } + + } + + static class NodeWithTwoChilds extends EmptyNode { + + @Child Node child1; + @Child Node child2; + + public NodeWithTwoChilds(Node child1, Node child2) { + this.child1 = adoptChild(child1); + this.child2 = adoptChild(child2); + } + + } + + static class NodeWithThreeChilds extends EmptyNode { + + @Child Node child1; + @Child Node child2; + @Child Node child3; + + public NodeWithThreeChilds(Node child1, Node child2, Node child3) { + this.child1 = adoptChild(child1); + this.child2 = adoptChild(child2); + this.child3 = adoptChild(child3); + } + + } + + static class NodeWithArray extends EmptyNode { + + @Children private final Node[] childNodes; + + NodeWithArray(Node[] children) { + this.childNodes = adoptChildren(children); + } + + Node[] getChildNodes() { + return childNodes; + } + } + + static class NodeWithTwoArray extends EmptyNode { + + @Children private final Node[] childNodes1; + @Children private final Node[] childNodes2; + + NodeWithTwoArray(Node[] childs1, Node[] childs2) { + this.childNodes1 = adoptChildren(childs1); + this.childNodes2 = adoptChildren(childs2); + } + + Node[] getChildNodes1() { + return childNodes1; + } + + Node[] getChildNodes2() { + return childNodes2; + } + } + + static class NodeWithFields extends EmptyNode { + + String stringField; + int integerField; + Integer integerObjectField; + long longField; + Long longObjectField; + float floatField; + Float floatObjectField; + double doubleField; + Double doubleObjectField; + char charField; + Character charObjectField; + short shortField; + Short shortObjecField; + byte byteField; + Byte byteObjectField; + boolean booleanField; + Boolean booleanObjectfield; + + public NodeWithFields(String stringField, int integerField, Integer integerObjectField, long longField, Long longObjectField, float floatField, Float floatObjectField, double doubleField, + Double doubleObjectField, char charField, Character charObjectField, short shortField, Short shortObjecField, byte byteField, Byte byteObjectField, boolean booleanField, + Boolean booleanObjectfield) { + this.stringField = stringField; + this.integerField = integerField; + this.integerObjectField = integerObjectField; + this.longField = longField; + this.longObjectField = longObjectField; + this.floatField = floatField; + this.floatObjectField = floatObjectField; + this.doubleField = doubleField; + this.doubleObjectField = doubleObjectField; + this.charField = charField; + this.charObjectField = charObjectField; + this.shortField = shortField; + this.shortObjecField = shortObjecField; + this.byteField = byteField; + this.byteObjectField = byteObjectField; + this.booleanField = booleanField; + this.booleanObjectfield = booleanObjectfield; + } + + @Override + public int hashCode() { + return Objects.hash(stringField, integerField, integerObjectField, longField, longObjectField, floatField, floatObjectField, doubleField, doubleObjectField, charField, charObjectField, + shortField, shortObjecField, byteField, byteObjectField, booleanField, booleanObjectfield); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj.getClass() != getClass()) { + return false; + } + NodeWithFields o = (NodeWithFields) obj; + return Objects.deepEquals(fieldArray(), o.fieldArray()); + } + + private Object[] fieldArray() { + return array(stringField, integerField, integerObjectField, longField, longObjectField, floatField, floatObjectField, doubleField, doubleObjectField, charField, charObjectField, + shortField, shortObjecField, byteField, byteObjectField, booleanField, booleanObjectfield); + } + + private static Object[] array(Object... values) { + return values; + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestSerializerConstantPool.java Tue Oct 15 21:28:24 2013 +0200 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 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.truffle.api.test.nodes.serial; + +import java.util.*; + +import com.oracle.truffle.api.nodes.serial.*; + +class TestSerializerConstantPool implements SerializerConstantPool { + + private final Map<Integer, Object> int2object = new HashMap<>(); + private final Map<Object, Integer> object2int = new HashMap<>(); + + private int index; + + public void setIndex(int index) { + this.index = index; + } + + public int getIndex() { + return index; + } + + @Override + public double getDouble(int cpi) { + return (Double) int2object.get(cpi); + } + + @Override + public float getFloat(int cpi) { + return (Float) int2object.get(cpi); + } + + @Override + public Object getObject(Class<?> clazz, int cpi) throws UnsupportedConstantPoolTypeException { + return int2object.get(cpi); + } + + @Override + public int putDouble(double value) { + return put(value); + } + + public int putFloat(float value) { + return put(value); + } + + public int putObject(java.lang.Class<?> clazz, Object value) throws UnsupportedConstantPoolTypeException { + return put(value); + } + + @Override + public int putClass(Class<?> clazz) { + return put(clazz); + } + + private int put(Object o) { + Integer currentIndex = object2int.get(o); + if (currentIndex == null) { + int2object.put(index, o); + object2int.put(o, index); + return index++; + } else { + return currentIndex; + } + } + + @Override + public Class<?> getClass(int idx) { + return (Class<?>) int2object.get(idx); + } + + @Override + public int putInt(int constant) { + return put(constant); + } + + @Override + public int getInt(int idx) { + return (Integer) int2object.get(idx); + } + + @Override + public long getLong(int idx) { + return (Long) int2object.get(idx); + } + + @Override + public int putLong(long value) { + return put(value); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/VariableLengthIntBufferTest.java Tue Oct 15 21:28:24 2013 +0200 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 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.truffle.api.test.nodes.serial; + +import java.nio.*; + +import org.junit.*; + +import com.oracle.truffle.api.nodes.serial.*; + +public class VariableLengthIntBufferTest { + + private VariableLengthIntBuffer buf; + + @Before + public void setUp() { + buf = new VariableLengthIntBuffer(ByteBuffer.allocate(512)); + } + + @After + public void tearDown() { + buf = null; + } + + @Test + public void testPutNull() { + buf.put(VariableLengthIntBuffer.NULL); + assertBytes(0xFF); + } + + @Test + public void testPutByteCornerCase0() { + buf.put(0x00); // 0 + assertBytes(0x00); + } + + @Test + public void testPutByteCornerCase1() { + buf.put(0x7F); // 127 + assertBytes(0x7F); + } + + @Test + public void testPutByteCornerCase2() { + buf.put(0x3FFF_FFFF); + assertBytes(0xBF, 0xFF, 0xFF, 0xFF); + } + + @Test(expected = IllegalArgumentException.class) + public void testPutByteCornerCase3() { + buf.put(0x4000_0000); // out of encodeable + } + + @Test + public void testGetNull() { + create(0xFF); + assertGet(VariableLengthIntBuffer.NULL); + } + + @Test + public void testGetCornerCase0() { + create(0x00); + assertGet(0x00); + } + + @Test + public void testGetCornerCase1() { + create(0x7F); + assertGet(0x7F); + } + + @Test + public void testGetCornerCase2() { + create(0xBF, 0xFF, 0xFF, 0xFF); + assertGet(0x3FFF_FFFF); + } + + @Test(expected = AssertionError.class) + public void testGetCornerCase3() { + create(0xFF, 0xFF, 0xFF, 0xFF); + assertGet(0x0); + } + + private void create(int... bytes) { + byte[] convBytes = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) { + convBytes[i] = (byte) bytes[i]; + } + buf = new VariableLengthIntBuffer(convBytes); + } + + private void assertGet(int expected) { + Assert.assertEquals(expected, buf.get()); + } + + private void assertBytes(int... expectedBytes) { + byte[] actualBytes = buf.getBytes(); + Assert.assertEquals(expectedBytes.length, actualBytes.length); + for (int i = 0; i < expectedBytes.length; i++) { + Assert.assertTrue(actualBytes[i] == (byte) expectedBytes[i]); + } + } + +}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Tue Oct 15 21:28:24 2013 +0200 @@ -28,6 +28,8 @@ import java.lang.reflect.*; import java.util.concurrent.*; +import com.oracle.truffle.api.frame.*; + import sun.misc.*; /** @@ -165,6 +167,20 @@ } /** + * Asserts that this value is not null and retrieved from a call to Frame.materialize. + * + * @param value the value that is known to have been obtained via Frame.materialize + * @return the value to be casted to the new type + */ + public static MaterializedFrame unsafeFrameCast(MaterializedFrame value) { + return unsafeCast(value, getUnsafeFrameType(), true); + } + + private static Class<? extends MaterializedFrame> getUnsafeFrameType() { + return MaterializedFrame.class; + } + + /** * Unsafe access to a boolean value within an object. The condition parameter gives a hint to * the compiler under which circumstances this access can be moved to an earlier location in the * program. The location identity gives a hint to the compiler for improved global value
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java Tue Oct 15 21:28:24 2013 +0200 @@ -70,6 +70,7 @@ * * @param slot the slot of the local variable * @return the current value of the local variable + * @throws FrameSlotTypeException */ byte getByte(FrameSlot slot) throws FrameSlotTypeException; @@ -80,7 +81,7 @@ * @param value the new value of the local variable */ - void setByte(FrameSlot slot, byte value) throws FrameSlotTypeException; + void setByte(FrameSlot slot, byte value); /** * Read access to a local variable of type boolean. @@ -96,7 +97,7 @@ * @param slot the slot of the local variable * @param value the new value of the local variable */ - void setBoolean(FrameSlot slot, boolean value) throws FrameSlotTypeException; + void setBoolean(FrameSlot slot, boolean value); /** * Read access to a local variable of type int. @@ -112,7 +113,7 @@ * @param slot the slot of the local variable * @param value the new value of the local variable */ - void setInt(FrameSlot slot, int value) throws FrameSlotTypeException; + void setInt(FrameSlot slot, int value); /** * Read access to a local variable of type long. @@ -128,7 +129,7 @@ * @param slot the slot of the local variable * @param value the new value of the local variable */ - void setLong(FrameSlot slot, long value) throws FrameSlotTypeException; + void setLong(FrameSlot slot, long value); /** * Read access to a local variable of type float. @@ -144,7 +145,7 @@ * @param slot the slot of the local variable * @param value the new value of the local variable */ - void setFloat(FrameSlot slot, float value) throws FrameSlotTypeException; + void setFloat(FrameSlot slot, float value); /** * Read access to a local variable of type double. @@ -160,7 +161,7 @@ * @param slot the slot of the local variable * @param value the new value of the local variable */ - void setDouble(FrameSlot slot, double value) throws FrameSlotTypeException; + void setDouble(FrameSlot slot, double value); /** * Read access to a local variable of any type.
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java Tue Oct 15 21:28:24 2013 +0200 @@ -29,7 +29,7 @@ private final FrameDescriptor descriptor; private final Object identifier; private final int index; - private FrameSlotKind kind; + @com.oracle.truffle.api.CompilerDirectives.CompilationFinal private FrameSlotKind kind; public FrameSlotImpl(FrameDescriptor descriptor, Object identifier, int index, FrameSlotKind kind) { this.descriptor = descriptor;
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotKind.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotKind.java Tue Oct 15 21:28:24 2013 +0200 @@ -25,5 +25,5 @@ package com.oracle.truffle.api.frame; public enum FrameSlotKind { - Illegal, Object, Long, Int, Double, Float, Boolean, Byte; + Object, Illegal, Long, Int, Double, Float, Boolean, Byte; }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java Tue Oct 15 21:28:24 2013 +0200 @@ -47,14 +47,7 @@ * @param value the new value of the local variable */ public static void setByteSafe(Frame frame, FrameSlot slot, byte value) { - if (slot.getKind() != FrameSlotKind.Byte) { - slot.setKind(FrameSlotKind.Byte); - } - try { - frame.setByte(slot, value); - } catch (FrameSlotTypeException e) { - throw new IllegalStateException(); - } + frame.setByte(slot, value); } /** @@ -66,14 +59,7 @@ * @param value the new value of the local variable */ public static void setBooleanSafe(Frame frame, FrameSlot slot, boolean value) { - if (slot.getKind() != FrameSlotKind.Boolean) { - slot.setKind(FrameSlotKind.Boolean); - } - try { - frame.setBoolean(slot, value); - } catch (FrameSlotTypeException e) { - throw new IllegalStateException(); - } + frame.setBoolean(slot, value); } /** @@ -85,14 +71,7 @@ * @param value the new value of the local variable */ public static void setIntSafe(Frame frame, FrameSlot slot, int value) { - if (slot.getKind() != FrameSlotKind.Int) { - slot.setKind(FrameSlotKind.Int); - } - try { - frame.setInt(slot, value); - } catch (FrameSlotTypeException e) { - throw new IllegalStateException(); - } + frame.setInt(slot, value); } /** @@ -104,14 +83,7 @@ * @param value the new value of the local variable */ public static void setLongSafe(Frame frame, FrameSlot slot, long value) { - if (slot.getKind() != FrameSlotKind.Long) { - slot.setKind(FrameSlotKind.Long); - } - try { - frame.setLong(slot, value); - } catch (FrameSlotTypeException e) { - throw new IllegalStateException(); - } + frame.setLong(slot, value); } /** @@ -123,14 +95,7 @@ * @param value the new value of the local variable */ public static void setFloatSafe(Frame frame, FrameSlot slot, float value) { - if (slot.getKind() != FrameSlotKind.Float) { - slot.setKind(FrameSlotKind.Float); - } - try { - frame.setFloat(slot, value); - } catch (FrameSlotTypeException e) { - throw new IllegalStateException(); - } + frame.setFloat(slot, value); } /** @@ -142,13 +107,6 @@ * @param value the new value of the local variable */ public static void setDoubleSafe(Frame frame, FrameSlot slot, double value) { - if (slot.getKind() != FrameSlotKind.Double) { - slot.setKind(FrameSlotKind.Double); - } - try { - frame.setDouble(slot, value); - } catch (FrameSlotTypeException e) { - throw new IllegalStateException(); - } + frame.setDouble(slot, value); } }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultFrameTypeConversion.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultFrameTypeConversion.java Tue Oct 15 21:28:24 2013 +0200 @@ -40,6 +40,9 @@ @Override public void updateFrameSlot(Frame frame, FrameSlot slot, Object value) { + if (slot.getKind() != FrameSlotKind.Object) { + slot.setKind(FrameSlotKind.Object); + } frame.setObject(slot, value); }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java Tue Oct 15 21:28:24 2013 +0200 @@ -56,7 +56,7 @@ } @Override - public void setByte(FrameSlot slot, byte value) throws FrameSlotTypeException { + public void setByte(FrameSlot slot, byte value) { wrapped.setByte(slot, value); } @@ -66,7 +66,7 @@ } @Override - public void setBoolean(FrameSlot slot, boolean value) throws FrameSlotTypeException { + public void setBoolean(FrameSlot slot, boolean value) { wrapped.setBoolean(slot, value); } @@ -76,7 +76,7 @@ } @Override - public void setInt(FrameSlot slot, int value) throws FrameSlotTypeException { + public void setInt(FrameSlot slot, int value) { wrapped.setInt(slot, value); } @@ -86,7 +86,7 @@ } @Override - public void setLong(FrameSlot slot, long value) throws FrameSlotTypeException { + public void setLong(FrameSlot slot, long value) { wrapped.setLong(slot, value); } @@ -96,7 +96,7 @@ } @Override - public void setFloat(FrameSlot slot, float value) throws FrameSlotTypeException { + public void setFloat(FrameSlot slot, float value) { wrapped.setFloat(slot, value); } @@ -106,7 +106,7 @@ } @Override - public void setDouble(FrameSlot slot, double value) throws FrameSlotTypeException { + public void setDouble(FrameSlot slot, double value) { wrapped.setDouble(slot, value); }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Tue Oct 15 21:28:24 2013 +0200 @@ -75,7 +75,7 @@ @Override public void setObject(FrameSlot slot, Object value) { - verifySetObject(slot); + verifySet(slot, FrameSlotKind.Object); locals[slot.getIndex()] = value; } @@ -86,7 +86,7 @@ } @Override - public void setByte(FrameSlot slot, byte value) throws FrameSlotTypeException { + public void setByte(FrameSlot slot, byte value) { verifySet(slot, FrameSlotKind.Byte); locals[slot.getIndex()] = value; } @@ -98,7 +98,7 @@ } @Override - public void setBoolean(FrameSlot slot, boolean value) throws FrameSlotTypeException { + public void setBoolean(FrameSlot slot, boolean value) { verifySet(slot, FrameSlotKind.Boolean); locals[slot.getIndex()] = value; } @@ -110,7 +110,7 @@ } @Override - public void setInt(FrameSlot slot, int value) throws FrameSlotTypeException { + public void setInt(FrameSlot slot, int value) { verifySet(slot, FrameSlotKind.Int); locals[slot.getIndex()] = value; } @@ -122,7 +122,7 @@ } @Override - public void setLong(FrameSlot slot, long value) throws FrameSlotTypeException { + public void setLong(FrameSlot slot, long value) { verifySet(slot, FrameSlotKind.Long); locals[slot.getIndex()] = value; } @@ -134,7 +134,7 @@ } @Override - public void setFloat(FrameSlot slot, float value) throws FrameSlotTypeException { + public void setFloat(FrameSlot slot, float value) { verifySet(slot, FrameSlotKind.Float); locals[slot.getIndex()] = value; } @@ -146,7 +146,7 @@ } @Override - public void setDouble(FrameSlot slot, double value) throws FrameSlotTypeException { + public void setDouble(FrameSlot slot, double value) { verifySet(slot, FrameSlotKind.Double); locals[slot.getIndex()] = value; } @@ -165,15 +165,7 @@ return locals[slotIndex]; } - 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(); - } - } + private void verifySet(FrameSlot slot, FrameSlotKind accessKind) { int slotIndex = slot.getIndex(); if (slotIndex >= tags.length) { resize(); @@ -181,24 +173,13 @@ tags[slotIndex] = (byte) accessKind.ordinal(); } - private void verifySetObject(FrameSlot slot) { - if (slot.getKind() != FrameSlotKind.Object) { - slot.setKind(FrameSlotKind.Object); - } - int slotIndex = slot.getIndex(); - if (slotIndex >= tags.length) { - resize(); - } - tags[slotIndex] = (byte) FrameSlotKind.Object.ordinal(); - } - private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { int slotIndex = slot.getIndex(); if (slotIndex >= tags.length) { resize(); } byte tag = tags[slotIndex]; - if (accessKind == FrameSlotKind.Object ? (tag & 0xfe) != 0 : tag != accessKind.ordinal()) { + if (accessKind == FrameSlotKind.Object ? tag != 0 : tag != accessKind.ordinal()) { if (slot.getKind() == accessKind || tag == 0) { descriptor.getTypeConversion().updateFrameSlot(this, slot, getValue(slot)); if (tags[slotIndex] == accessKind.ordinal()) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java Tue Oct 15 21:28:24 2013 +0200 @@ -0,0 +1,366 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.nodes.serial; + +import java.lang.reflect.*; +import java.util.*; + +import sun.misc.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.*; + +/** + * Experimental API. May change without notice. + */ +public final class PostOrderDeserializer { + + private static final Unsafe unsafe = loadUnsafe(); + + private final SerializerConstantPool cp; + + private final HierarchicalStack stack = new HierarchicalStack(); + + /** + * Constructs a new serializer using a custom {@link SerializerConstantPool} implementation. For + * the {@link SerializerConstantPool} implementation at least the following methods must be + * implemented: + * <ul> + * <li>{@link SerializerConstantPool#getInt(int)}</li> + * <li>{@link SerializerConstantPool#getClass(int)}</li> + * </ul> + */ + public PostOrderDeserializer(SerializerConstantPool cp) { + this.cp = cp; + } + + /** + * Deserializes the byte stream and returns the deserialized Truffle AST node. + * + * @param bytes the trimmed byte array containing the serialized data + * @param expectedType the expected root node type. Throws an exception if the root node is not + * assignable from this type. + * @return the deserialized Truffle AST represented by the root Node. + * + * @throws UnsupportedConstantPoolTypeException thrown if a type is encountered that is not + * supported by the constant pool implementation. + */ + @SuppressWarnings("unchecked") + public <T extends Node> T deserialize(byte[] bytes, Class<T> expectedType) throws UnsupportedConstantPoolTypeException { + VariableLengthIntBuffer buffer = new VariableLengthIntBuffer(bytes); + + while (buffer.hasRemaining()) { + int classCPI = buffer.get(); + if (classCPI == VariableLengthIntBuffer.NULL) { + pushNode(null); + } else { + Class<?> clazz = cp.getClass(classCPI); + if (clazz.isArray()) { + int lengthCPI = buffer.get(); + if (lengthCPI == VariableLengthIntBuffer.NULL) { + pushArray(null); + } else { + pushArray((Node[]) Array.newInstance(clazz.getComponentType(), cp.getInt(lengthCPI))); + } + } else { + pushNode(invokeDeserialize(buffer, clazz.asSubclass(Node.class))); + } + } + } + T returnNode = (T) popNode(null, expectedType); + + assert stack.dynamicStack.isEmpty(); + + return returnNode; + } + + private void pushNode(Node node) { + stack.push(node); + } + + private void pushArray(Node[] array) { + stack.pushStack(array); + } + + private Node[] popArray(Node parent, Class<?> expectedType) { + Node[] array = (Node[]) stack.popStack(); + if (array != null) { + assertType(array, expectedType); + for (int i = 0; i < array.length; i++) { + updateParent(parent, array[i]); + } + } + return array; + } + + private Node popNode(Node parent, Class<?> expectedType) { + Object o = stack.pop(); + assertType(o, expectedType); + updateParent(parent, (Node) o); + return (Node) o; + } + + private static void assertType(Object o, Class<?> expectedType) { + if (o != null && !expectedType.isAssignableFrom(o.getClass())) { + throw new AssertionError("Expected element type '" + expectedType.getName() + "' but was '" + o.getClass().getName() + "'."); + } + } + + private Node invokeDeserialize(VariableLengthIntBuffer buffer, Class<? extends Node> nodeClass) throws UnsupportedConstantPoolTypeException { + if (nodeClass == null) { + return null; + } + + Object object; + try { + object = unsafe.allocateInstance(nodeClass); + } catch (InstantiationException e) { + throw new RuntimeException("Unable to allocate truffle node " + nodeClass, e); + } + if (!(object instanceof Node)) { + throw new RuntimeException("Class is not a truffle node " + nodeClass); + } + + Node node = (Node) object; + + NodeField[] nodeFields = NodeClass.get(nodeClass).getFields(); + deserializeChildrenFields(node, nodeFields); + deserializeChildFields(node, nodeFields); + deserializeDataFields(buffer, node, nodeFields); + + return node; + } + + private void deserializeDataFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeField[] nodeFields) throws UnsupportedConstantPoolTypeException { + for (int i = 0; i < nodeFields.length; i++) { + NodeField field = nodeFields[i]; + if (field.getKind() == NodeFieldKind.DATA) { + Class<?> fieldClass = field.getType(); + long offset = field.getOffset(); + + // source sections are not serialized + // TODO add support for source sections + if (field.getType().isAssignableFrom(SourceSection.class)) { + continue; + } + + int cpi = buffer.get(); + if (cpi == VariableLengthIntBuffer.NULL) { + if (fieldClass == int.class) { + unsafe.putInt(nodeInstance, offset, 0); + } else if (fieldClass == long.class) { + unsafe.putLong(nodeInstance, offset, 0L); + } else if (fieldClass == float.class) { + unsafe.putFloat(nodeInstance, offset, 0.0F); + } else if (fieldClass == double.class) { + unsafe.putDouble(nodeInstance, offset, 0.0D); + } else if (fieldClass == byte.class) { + unsafe.putByte(nodeInstance, offset, (byte) 0); + } else if (fieldClass == short.class) { + unsafe.putShort(nodeInstance, offset, (short) 0); + } else if (fieldClass == char.class) { + unsafe.putChar(nodeInstance, offset, (char) 0); + } else if (fieldClass == boolean.class) { + unsafe.putBoolean(nodeInstance, offset, false); + } else { + unsafe.putObject(nodeInstance, offset, null); + } + } else { + if (fieldClass == int.class) { + unsafe.putInt(nodeInstance, offset, cp.getInt(cpi)); + } else if (fieldClass == long.class) { + unsafe.putLong(nodeInstance, offset, cp.getLong(cpi)); + } else if (fieldClass == float.class) { + unsafe.putFloat(nodeInstance, offset, cp.getFloat(cpi)); + } else if (fieldClass == double.class) { + unsafe.putDouble(nodeInstance, offset, cp.getDouble(cpi)); + } else if (fieldClass == byte.class) { + unsafe.putByte(nodeInstance, offset, (byte) cp.getInt(cpi)); + } else if (fieldClass == short.class) { + unsafe.putShort(nodeInstance, offset, (short) cp.getInt(cpi)); + } else if (fieldClass == char.class) { + unsafe.putChar(nodeInstance, offset, (char) cp.getInt(cpi)); + } else if (fieldClass == boolean.class) { + unsafe.putBoolean(nodeInstance, offset, cp.getInt(cpi) == 1 ? true : false); + } else if (fieldClass == Integer.class) { + unsafe.putObject(nodeInstance, offset, cp.getInt(cpi)); + } else if (fieldClass == Long.class) { + unsafe.putObject(nodeInstance, offset, cp.getLong(cpi)); + } else if (fieldClass == Float.class) { + unsafe.putObject(nodeInstance, offset, cp.getFloat(cpi)); + } else if (fieldClass == Double.class) { + unsafe.putObject(nodeInstance, offset, cp.getDouble(cpi)); + } else if (fieldClass == Byte.class) { + unsafe.putObject(nodeInstance, offset, (byte) cp.getInt(cpi)); + } else if (fieldClass == Short.class) { + unsafe.putObject(nodeInstance, offset, (short) cp.getInt(cpi)); + } else if (fieldClass == Character.class) { + unsafe.putObject(nodeInstance, offset, (char) cp.getInt(cpi)); + } else if (fieldClass == Boolean.class) { + unsafe.putObject(nodeInstance, offset, cp.getInt(cpi) == 1 ? Boolean.TRUE : Boolean.FALSE); + } else { + unsafe.putObject(nodeInstance, offset, cp.getObject(fieldClass, cpi)); + } + } + } + } + } + + private void deserializeChildFields(Node parent, NodeField[] nodeFields) { + for (int i = nodeFields.length - 1; i >= 0; i--) { + NodeField field = nodeFields[i]; + if (field.getKind() == NodeFieldKind.CHILD) { + unsafe.putObject(parent, field.getOffset(), popNode(parent, field.getType())); + } + } + } + + private void deserializeChildrenFields(Node parent, NodeField[] nodeFields) { + for (int i = nodeFields.length - 1; i >= 0; i--) { + NodeField field = nodeFields[i]; + if (field.getKind() == NodeFieldKind.CHILDREN) { + unsafe.putObject(parent, field.getOffset(), popArray(parent, field.getType())); + } + } + } + + private static Node updateParent(Node parent, Node child) { + if (child != null) { + long parentOffset = NodeClass.get(child.getClass()).getParentOffset(); + unsafe.putObject(child, parentOffset, parent); + } + return child; + } + + private static Unsafe loadUnsafe() { + try { + return Unsafe.getUnsafe(); + } catch (SecurityException e) { + } + try { + Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeInstance.setAccessible(true); + return (Unsafe) theUnsafeInstance.get(Unsafe.class); + } catch (Exception e) { + throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); + } + } + + private static class HierarchicalStack { + + private static final Object NULL_STACK = new Object(); + + private final List<Object> dynamicStack = new ArrayList<>(); + + void pushStack(Object[] array) { + if (array == null) { + dynamicStack.add(NULL_STACK); + } else { + dynamicStack.add(new FixedSizeNodeStack(array)); + } + } + + private FixedSizeNodeStack getTosStack() { + if (dynamicStack.isEmpty()) { + return null; + } + Object peekTos = dynamicStack.get(dynamicStack.size() - 1); + if (peekTos != null && peekTos.getClass() == FixedSizeNodeStack.class) { + return (FixedSizeNodeStack) peekTos; + } + return null; + } + + Object[] popStack() { + Object tos = dynamicStack.remove(dynamicStack.size() - 1); + if (tos == NULL_STACK) { + return null; + } + return ((FixedSizeNodeStack) tos).getArray(); + } + + void push(Object o) { + FixedSizeNodeStack tosStack = getTosStack(); + if (tosStack != null && !tosStack.isFull()) { + tosStack.push(o); + } else { + dynamicStack.add(o); + } + } + + Object pop() { + FixedSizeNodeStack tosStack = getTosStack(); + Object value; + if (tosStack != null) { + assert !tosStack.isEmpty(); + value = tosStack.pop(); + } else { + value = dynamicStack.remove(dynamicStack.size() - 1); + } + assert value != NULL_STACK; + return value; + } + + } + + private static class FixedSizeNodeStack { + + private final Object[] array; + + private int tos; + + FixedSizeNodeStack(Object[] array) { + this.array = array; + } + + boolean isFull() { + return tos == array.length; + } + + boolean isEmpty() { + return tos == 0; + } + + private void push(Object node) { + if (tos >= array.length) { + throw new ArrayIndexOutOfBoundsException(); + } + unsafe.putObject(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * (long) (tos++), node); + } + + private Object pop() { + if (tos <= 0) { + throw new ArrayIndexOutOfBoundsException(); + } + return unsafe.getObject(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * (long) (--tos)); + } + + private Object[] getArray() { + return array; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderSerializer.java Tue Oct 15 21:28:24 2013 +0200 @@ -0,0 +1,199 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.nodes.serial; + +import java.lang.reflect.*; +import java.nio.*; + +import sun.misc.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.NodeClass; +import com.oracle.truffle.api.nodes.NodeUtil.NodeField; +import com.oracle.truffle.api.nodes.NodeUtil.NodeFieldKind; + +/** + * Experimental API. May change without notice. + */ +public final class PostOrderSerializer { + + private static final Unsafe unsafe = loadUnsafe(); + + private final SerializerConstantPool cp; + + /** + * Constructs a new deserializer using a custom {@link SerializerConstantPool} implementation. + * For the {@link SerializerConstantPool} implementation at least the following methods must be + * implemented: + * <ul> + * <li>{@link SerializerConstantPool#putInt(int)}</li> + * <li>{@link SerializerConstantPool#putClass(Class)}</li> + * </ul> + */ + public PostOrderSerializer(SerializerConstantPool cp) { + this.cp = cp; + } + + /** + * Serializes the node AST and returns the serialized data as byte array. + * + * @param node the root node that represents the Truffle AST that should be serialized. + * @return a trimmed byte array that contains the serialized data. + * + * @throws UnsupportedConstantPoolTypeException thrown if a type is encountered that is not + * supported by the constant pool implementation. + */ + public byte[] serialize(Node node) throws UnsupportedConstantPoolTypeException { + VariableLengthIntBuffer buffer = new VariableLengthIntBuffer(ByteBuffer.allocate(512)); + serialize(buffer, node); + return buffer.getBytes(); + } + + private void serialize(VariableLengthIntBuffer buffer, Node node) throws UnsupportedConstantPoolTypeException { + if (node == null) { + buffer.put(VariableLengthIntBuffer.NULL); + return; + } + Class<? extends Node> nodeClass = node.getClass(); + + NodeField[] nodeFields = NodeClass.get(nodeClass).getFields(); + serializeChildFields(buffer, node, nodeFields); + serializeChildrenFields(buffer, node, nodeFields); + buffer.put(cp.putClass(node.getClass())); + serializeDataFields(buffer, node, nodeFields); + } + + private void serializeDataFields(VariableLengthIntBuffer buffer, Node node, NodeField[] nodeFields) throws UnsupportedConstantPoolTypeException { + for (int i = 0; i < nodeFields.length; i++) { + NodeField field = nodeFields[i]; + if (field.getKind() == NodeFieldKind.DATA) { + Class<?> fieldClass = field.getType(); + long offset = field.getOffset(); + int cpi; + + if (field.getType().isAssignableFrom(SourceSection.class)) { + continue; + } + + if (fieldClass == int.class) { + cpi = cp.putInt(unsafe.getInt(node, offset)); + } else if (fieldClass == long.class) { + cpi = cp.putLong(unsafe.getLong(node, offset)); + } else if (fieldClass == float.class) { + cpi = cp.putFloat(unsafe.getFloat(node, offset)); + } else if (fieldClass == double.class) { + cpi = cp.putDouble(unsafe.getDouble(node, offset)); + } else if (fieldClass == byte.class) { + cpi = cp.putInt(unsafe.getByte(node, offset)); + } else if (fieldClass == short.class) { + cpi = cp.putInt(unsafe.getShort(node, offset)); + } else if (fieldClass == char.class) { + cpi = cp.putInt(unsafe.getChar(node, offset)); + } else if (fieldClass == boolean.class) { + cpi = cp.putInt(unsafe.getBoolean(node, offset) ? 1 : 0); + } else { + Object value = unsafe.getObject(node, offset); + if (value == null) { + cpi = VariableLengthIntBuffer.NULL; + } else if (fieldClass == Integer.class) { + cpi = cp.putInt((Integer) value); + } else if (fieldClass == Long.class) { + cpi = cp.putLong((Long) value); + } else if (fieldClass == Float.class) { + cpi = cp.putFloat((Float) value); + } else if (fieldClass == Double.class) { + cpi = cp.putDouble((Double) value); + } else if (fieldClass == Byte.class) { + cpi = cp.putInt((Byte) value); + } else if (fieldClass == Short.class) { + cpi = cp.putInt((Short) value); + } else if (fieldClass == Character.class) { + cpi = cp.putInt((Character) value); + } else if (fieldClass == Boolean.class) { + cpi = cp.putInt((Boolean) value ? 1 : 0); + } else { + cpi = cp.putObject(fieldClass, value); + } + } + + buffer.put(cpi); + } + } + } + + private void serializeChildrenFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeField[] nodeFields) throws UnsupportedConstantPoolTypeException { + for (int i = 0; i < nodeFields.length; i++) { + NodeField field = nodeFields[i]; + if (field.getKind() == NodeFieldKind.CHILDREN) { + Object childArrayObject = unsafe.getObject(nodeInstance, field.getOffset()); + if (childArrayObject != null && !(childArrayObject instanceof Node[])) { + throw new AssertionError("Node children must be instanceof Node[]"); + } + + buffer.put(cp.putClass(field.getType())); + + Node[] childArray = (Node[]) childArrayObject; + if (childArray == null) { + buffer.put(VariableLengthIntBuffer.NULL); + } else { + buffer.put(cp.putInt(childArray.length)); + + for (int j = 0; j < childArray.length; j++) { + serialize(buffer, childArray[j]); + } + } + } + } + } + + private void serializeChildFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeField[] nodeFields) throws UnsupportedConstantPoolTypeException { + for (int i = 0; i < nodeFields.length; i++) { + NodeField field = nodeFields[i]; + if (field.getKind() == NodeFieldKind.CHILD) { + Object childObject = unsafe.getObject(nodeInstance, field.getOffset()); + if (childObject != null && !(childObject instanceof Node)) { + throw new AssertionError("Node children must be instanceof Node"); + } + serialize(buffer, (Node) childObject); + } + } + } + + private static Unsafe loadUnsafe() { + try { + return Unsafe.getUnsafe(); + } catch (SecurityException e) { + } + try { + Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeInstance.setAccessible(true); + return (Unsafe) theUnsafeInstance.get(Unsafe.class); + } catch (Exception e) { + throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/SerializerConstantPool.java Tue Oct 15 21:28:24 2013 +0200 @@ -0,0 +1,152 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.nodes.serial; + +/** + * Experimental API. May change without notice. This interface is used as bridge between the + * {@link PostOrderDeserializer}, {@link PostOrderSerializer} and underlying constant pool + * implementation. A constant pool stores a value and returns an identifying index, with which the + * object can later be returned from the pool again. All methods of this class are optional and may + * throw a {@link UnsupportedOperationException}. + */ +public interface SerializerConstantPool { + + /** + * Returns the constant pool index of a value that is not a java native type, a java + * native-wrapper class or a {@link Class} instance. The implementor should support all + * additional types that are necessary to serialize a truffle AST for a specific truffle + * implementation. If a type is not supported by this constant pool implementation a + * {@link UnsupportedConstantPoolTypeException} should be thrown. + * + * @param clazz the {@link Class} of the value + * @param value the value to be stored. Must be at least a subclass of the given clazz. + * @return the constant pool index + * @throws UnsupportedConstantPoolTypeException if a type is not supported for persistence in + * the constant pool. + */ + int putObject(Class<?> clazz, Object value) throws UnsupportedConstantPoolTypeException; + + /** + * Stores a value in the constant pool that is not a java native type, a java native-wrapper + * class or a {@link Class} instance. The implementor should support all additional types that + * are necessary to serialize a truffle AST for a specific truffle implementation. If a type is + * not supported by this constant pool implementation a + * {@link UnsupportedConstantPoolTypeException} should be thrown. + * + * @param clazz the {@link Class} of the value in the constant pool. + * @param cpi the previously returned index + * @return the value stored inside the constant pool + * @throws UnsupportedConstantPoolTypeException if a type is not supported for persistence in + * the constant pool. + * @throws IllegalArgumentException if the provided cpi is not a valid constant pool index. + */ + Object getObject(Class<?> clazz, int cpi) throws UnsupportedConstantPoolTypeException; + + /** + * Stores a Class instance in the constant pool and returns the constant pool index. + * + * @param value the class to store + * @return the new or existing constant pool index of the Class + */ + int putClass(Class<?> value); + + /** + * Returns the {@link Class} instance to the given constant pool index. + * + * @param cpi the constant pool index + * @return stored value + * @throws IllegalArgumentException if the constant pool indes is invalid. + */ + Class<?> getClass(int cpi); + + /** + * Stores an int value in the constant pool and returns the constant pool index. + * + * @param value the value to store + * @return the new or existing constant pool index of the value + */ + int putInt(int value); + + /** + * Returns the stored int value to the given constant pool index from the constant pool. + * + * @param cpi the constant pool index + * @return stored value + * @throws IllegalArgumentException if the constant pool index is invalid. + */ + int getInt(int cpi); + + /** + * Stores a long value in the constant pool and returns the constant pool index. + * + * @param value the value to store + * @return the new or existing constant pool index of the value + */ + int putLong(long value); + + /** + * Returns the stored long value to the given constant pool index from the constant pool. + * + * @param cpi the constant pool index + * @return the stored value + * @throws IllegalArgumentException if the constant pool index is invalid. + */ + long getLong(int cpi); + + /** + * Stores a double value in the constant pool and returns the constant pool index. + * + * @param value the value to store + * @return the new or existing constant pool index of the value + */ + int putDouble(double value); + + /** + * Returns the stored double value to the given constant pool index from the constant pool. + * + * @param cpi the constant pool index + * @return the stored value + * @throws IllegalArgumentException if the constant pool index is invalid. + */ + double getDouble(int cpi); + + /** + * Stores a float value in the constant pool and returns the constant pool index. + * + * @param value the value to store + * @return the new or existing constant pool index of the value + */ + int putFloat(float value); + + /** + * Returns the stored float value to the given constant pool index from the constant pool. + * + * @param cpi the constant pool index + * @return the stored value + * @throws IllegalArgumentException if the constant pool index is invalid. + */ + float getFloat(int cpi); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/UnsupportedConstantPoolTypeException.java Tue Oct 15 21:28:24 2013 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.nodes.serial; + +/** + * Experimental API. May change without notice. + */ +public class UnsupportedConstantPoolTypeException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public UnsupportedConstantPoolTypeException() { + super(); + } + + public UnsupportedConstantPoolTypeException(String message, Throwable cause) { + super(message, cause); + } + + public UnsupportedConstantPoolTypeException(String message) { + super(message); + } + + public UnsupportedConstantPoolTypeException(Throwable cause) { + super(cause); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/VariableLengthIntBuffer.java Tue Oct 15 21:28:24 2013 +0200 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.nodes.serial; + +import java.nio.*; + +/** + * Experimental API. May change without notice. Simple variable length unsigned int buffer backed by + * a byte buffer. + */ +public class VariableLengthIntBuffer { + + public static final int NULL = -1; + + private ByteBuffer buffer; + + public VariableLengthIntBuffer(ByteBuffer buffer) { + this.buffer = buffer; + } + + public VariableLengthIntBuffer(byte[] array) { + buffer = ByteBuffer.wrap(array); + } + + /** + * Returns the backing byte buffer. + */ + public ByteBuffer getBuffer() { + return buffer; + } + + public byte[] getBytes() { + int pos = buffer.position(); + byte[] bytes = new byte[buffer.position()]; + buffer.rewind(); + buffer.get(bytes); + buffer.position(pos); + return bytes; + } + + public int get() { + byte peekByte = buffer.get(buffer.position()); + if ((peekByte & 0x80) == 0) { + // single byte encoding with prefix 0 (range 127) + return buffer.get(); // no bit to be masked + } else { + if (peekByte == (byte) 0xFF) { + buffer.get(); // skip one byte + return NULL; + } + int result = buffer.getInt() & 0x7FFF_FFFF; // first bit masked out + assert (result & 0x4000_0000) == 0; + return result; + } + } + + public void put(int i) { + ensureCapacity(); + if (i == NULL) { + buffer.put((byte) 0xFF); + } else if ((i & 0xFFFF_FF80) == 0) { // 7 bits data + buffer.put((byte) i); + } else if ((i & 0xC000_0000) == 0) { // 32 bits data + buffer.putInt(i | 0x8000_0000); // append leading 1 + } else { + throw new IllegalArgumentException("Integer out of encodeable " + i); + } + } + + private void ensureCapacity() { + if (buffer.position() + 4 > buffer.capacity()) { + ByteBuffer newBuffer = ByteBuffer.allocate(buffer.capacity() * 2); + + int pos = buffer.position(); + buffer.rewind(); + newBuffer.put(buffer); + newBuffer.position(pos); + + buffer = newBuffer; + } + } + + public boolean hasRemaining() { + return buffer.hasRemaining(); + } + +}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Tue Oct 15 21:28:24 2013 +0200 @@ -58,6 +58,7 @@ private final DeclaredType slowPath; private final DeclaredType sourceSection; private final DeclaredType truffleOptions; + private final DeclaredType compilationFinal; private final TypeElement expectError; private final List<String> errors = new ArrayList<>(); @@ -78,9 +79,14 @@ slowPath = getRequired(context, SlowPath.class); sourceSection = getRequired(context, SourceSection.class); truffleOptions = getRequired(context, TruffleOptions.class); + compilationFinal = getRequired(context, CompilationFinal.class); expectError = (TypeElement) getRequired(context, ExpectError.class).asElement(); } + public DeclaredType getCompilationFinal() { + return compilationFinal; + } + public TypeElement getExpectError() { return expectError; }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElement.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElement.java Tue Oct 15 21:28:24 2013 +0200 @@ -78,6 +78,13 @@ return element; } + public E addOptional(E element) { + if (element != null) { + add(element); + } + return element; + } + public void remove(E element) { getEnclosedElements().remove(element); }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeData.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeData.java Tue Oct 15 21:28:24 2013 +0200 @@ -37,6 +37,9 @@ super(method, executable); this.typeSystem = typeSystem; this.type = type; + if (executable.getParameters().size() < method.getMethod().getParameters().size()) { + throw new IllegalArgumentException(String.format("Method parameter count mismatch %s != %s.", executable.getParameters(), method.getMethod().getParameters())); + } } public TypeData getType() {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Tue Oct 15 21:28:24 2013 +0200 @@ -40,7 +40,6 @@ import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard; import com.oracle.truffle.dsl.processor.template.*; -import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature; import com.oracle.truffle.dsl.processor.typesystem.*; public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> { @@ -50,6 +49,8 @@ private static final String EXECUTE_GENERIC_NAME = "executeGeneric0"; private static final String EXECUTE_SPECIALIZE_NAME = "executeAndSpecialize0"; + private static final String UPDATE_TYPES_NAME = "updateTypes"; + public NodeCodeGenerator(ProcessorContext context) { super(context); } @@ -62,15 +63,6 @@ return node.getNodeId() + "Factory"; } - private static String nodeCastClassName(NodeData node, TypeData type) { - String nodeid = resolveNodeId(node); - if (type == null) { - return nodeid + "ImplicitCast"; - } else { - return Utils.firstLetterUpperCase(Utils.getSimpleName(type.getPrimitiveType())) + "Cast"; - } - } - private static String nodeSpecializationClassName(SpecializationData specialization) { String nodeid = resolveNodeId(specialization.getNode()); String name = Utils.firstLetterUpperCase(nodeid); @@ -103,8 +95,12 @@ return valueName(targetParameter) + "Evaluated"; } - private static String typeName(ActualParameter param) { - return param.getLocalName() + "Type"; + private static String implicitTypeName(ActualParameter param) { + return param.getLocalName() + "ImplicitType"; + } + + private static String polymorphicTypeName(ActualParameter param) { + return param.getLocalName() + "PolymorphicType"; } private static String valueName(ActualParameter param) { @@ -299,7 +295,7 @@ builder.string(targetParameter.getSpecification().getName()); builder.end(); } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { - builder.string("ex.getResult()"); + builder.cast(targetParameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); } else if (!Utils.needsCastTo(getContext(), valueType, targetType)) { builder.startGroup(); builder.string(valueName(targetParameter)); @@ -321,16 +317,18 @@ return name; } - private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, CodeTree value) { + private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, CodeTree... args) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); - startCallTypeSystemMethod(context, builder, node, methodName); - builder.tree(value); + startCallTypeSystemMethod(context, builder, node.getTypeSystem(), methodName); + for (CodeTree arg : args) { + builder.tree(arg); + } builder.end().end(); return builder.getRoot(); } - private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, NodeData node, String methodName) { - VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, node.getTypeSystem()); + private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, TypeSystemData typeSystem, String methodName) { + VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, typeSystem); assert singleton != null; body.startGroup(); @@ -456,7 +454,7 @@ } } - protected CodeTree createCastType(NodeData node, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) { + protected CodeTree createCastType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) { if (targetType == null) { return value; } else if (sourceType != null && !sourceType.needsCastTo(getContext(), targetType)) { @@ -470,12 +468,16 @@ } else { targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); } - startCallTypeSystemMethod(getContext(), builder, node, targetMethodName); + startCallTypeSystemMethod(getContext(), builder, typeSystem, targetMethodName); builder.tree(value); builder.end().end(); return builder.getRoot(); } + protected CodeTree createExpectType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, CodeTree expression) { + return createCastType(typeSystem, sourceType, targetType, true, expression); + } + private class NodeFactoryFactory extends ClassElementFactory<NodeData> { private final Map<NodeData, List<TypeElement>> childTypes; @@ -504,6 +506,7 @@ Modifier createVisibility = Utils.getVisibility(clazz.getModifiers()); + CodeTypeElement polymorphicNode = null; if (node.needsFactory()) { NodeBaseFactory factory = new NodeBaseFactory(context); add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization()); @@ -516,15 +519,9 @@ createFactoryMethods(node, clazz, createVisibility); if (node.isPolymorphic()) { - PolymorphicNodeFactory generic = new PolymorphicNodeFactory(getContext(), generatedNode, true); + PolymorphicNodeFactory generic = new PolymorphicNodeFactory(getContext(), generatedNode); add(generic, node.getGenericPolymorphicSpecialization()); - - for (SpecializationData specialization : node.getPolymorphicSpecializations()) { - if (specialization == node.getGenericPolymorphicSpecialization()) { - continue; - } - add(new PolymorphicNodeFactory(context, generic.getElement(), false), specialization); - } + polymorphicNode = generic.getElement(); } for (SpecializationData specialization : node.getSpecializations()) { if (!specialization.isReachable()) { @@ -544,6 +541,10 @@ clazz.add(createInstanceConstant(node, clazz.asType())); } + if (polymorphicNode != null) { + patchParameterType(clazz, UPDATE_TYPES_NAME, generatedNode.asType(), polymorphicNode.asType()); + } + for (NodeData childNode : childTypes.keySet()) { if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { continue; @@ -570,6 +571,19 @@ } + private void patchParameterType(CodeTypeElement enclosingClass, String methodName, TypeMirror originalType, TypeMirror newType) { + for (TypeElement enclosedType : ElementFilter.typesIn(enclosingClass.getEnclosedElements())) { + CodeTypeElement type = (CodeTypeElement) enclosedType; + ExecutableElement method = type.getMethod(methodName); + for (VariableElement v : method.getParameters()) { + CodeVariableElement var = (CodeVariableElement) v; + if (Utils.typeEquals(var.getType(), originalType)) { + var.setType(newType); + } + } + } + } + private CodeExecutableElement createGetNodeClassMethod(NodeData node) { TypeMirror returnType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType()); CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass"); @@ -941,16 +955,14 @@ builder.statement("this.next0 = adoptChild(next0)"); clazz.add(setter); - createIsCompatible(clazz, null); - - CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecialization(), null); + CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecialization()); clazz.add(genericCachedExecute); - for (SpecializationData polymorph : node.getPolymorphicSpecializations()) { - if (polymorph == node.getGenericPolymorphicSpecialization()) { - continue; - } - clazz.add(createCachedExecute(node, polymorph, genericCachedExecute)); - } + + getElement().add(createUpdateTypes(clazz.asType())); + } + + for (CodeExecutableElement method : createImplicitChildrenAccessors()) { + clazz.add(method); } clazz.add(createGenericExecuteAndSpecialize(node, rootGroup)); @@ -962,6 +974,59 @@ } } + private List<CodeExecutableElement> createImplicitChildrenAccessors() { + NodeData node = getModel().getNode(); +// Map<NodeChildData, Set<TypeData>> expectTypes = new HashMap<>(); + @SuppressWarnings("unchecked") + List<Set<TypeData>> expectTypes = Arrays.<Set<TypeData>> asList(new Set[node.getGenericSpecialization().getParameters().size()]); + + for (ExecutableTypeData executableType : node.getExecutableTypes()) { + for (int i = 0; i < executableType.getEvaluatedCount(); i++) { + ActualParameter parameter = executableType.getSignatureParameter(i); + if (i >= expectTypes.size()) { + break; + } + Set<TypeData> types = expectTypes.get(i); + if (types == null) { + types = new TreeSet<>(); + expectTypes.set(i, types); + } + types.add(parameter.getTypeSystemType()); + } + } + + List<CodeExecutableElement> methods = new ArrayList<>(); + @SuppressWarnings("unchecked") + List<Set<TypeData>> visitedList = Arrays.<Set<TypeData>> asList(new Set[node.getGenericSpecialization().getParameters().size()]); + for (SpecializationData spec : node.getSpecializations()) { + int signatureIndex = -1; + for (ActualParameter param : spec.getParameters()) { + if (!param.getSpecification().isSignature()) { + continue; + } + signatureIndex++; + Set<TypeData> visitedTypeData = visitedList.get(signatureIndex); + if (visitedTypeData == null) { + visitedTypeData = new TreeSet<>(); + visitedList.set(signatureIndex, visitedTypeData); + } + + if (visitedTypeData.contains(param.getTypeSystemType())) { + continue; + } + visitedTypeData.add(param.getTypeSystemType()); + + Set<TypeData> expect = expectTypes.get(signatureIndex); + if (expect == null) { + expect = Collections.emptySet(); + } + + methods.addAll(createExecuteChilds(param, expect)); + } + } + return methods; + } + private CodeTree truffleBooleanOption(CodeTreeBuilder parent, String name) { CodeTreeBuilder builder = parent.create(); builder.staticReference(getContext().getTruffleTypes().getTruffleOptions(), name); @@ -1028,53 +1093,10 @@ return method; } - protected void createIsCompatible(CodeTypeElement clazz, SpecializationData specialization) { - CodeExecutableElement isCompatible = new CodeExecutableElement(modifiers(PROTECTED), context.getType(boolean.class), "isCompatible0"); - isCompatible.addParameter(new CodeVariableElement(getContext().getType(Class.class), "type")); - - if (specialization == null) { - isCompatible.getModifiers().add(ABSTRACT); - } else if (specialization.isGeneric()) { - isCompatible.createBuilder().startThrow().startNew(getContext().getType(AssertionError.class)).end().end(); - } else if (specialization.isPolymorphic()) { - isCompatible.createBuilder().startReturn().string("type != getClass() && next0.isCompatible0(type)").end(); - } else if (specialization.isUninitialized()) { - isCompatible.createBuilder().returnTrue(); - } else { - NodeData node = specialization.getNode(); - CodeTreeBuilder builder = isCompatible.createBuilder(); - - Signature specializationSignature = specialization.getSignature(); - List<SpecializationData> compatible = new ArrayList<>(); - for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) { - if (specializationSignature.isCompatibleTo(polymorphic.getSignature())) { - compatible.add(polymorphic); - } - } - - if (compatible.isEmpty()) { - builder.returnFalse(); - } else { - builder.startIf(); - String and = ""; - for (SpecializationData polymorphic : compatible) { - builder.string(and); - builder.string("type == ").string(nodePolymorphicClassName(node, polymorphic)).string(".class"); - and = " || "; - } - builder.end().startBlock(); - builder.startReturn().startCall("next0", "isCompatible0").string("type").end().end(); - builder.end(); - builder.returnFalse(); - } - } - - clazz.add(isCompatible); - } - - private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph, CodeExecutableElement genericPolymorphMethod) { + private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) { String name = executeCachedName(polymorph); - CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name); + CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), name); + addInternalValueParameters(cachedExecute, polymorph, true, true); ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0); boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext()); @@ -1084,18 +1106,6 @@ if (sourceThrowsUnexpected) { cachedExecute.getThrownTypes().add(getContext().getType(UnexpectedResultException.class)); } - addInternalValueParameters(cachedExecute, polymorph, true, true); - - if (polymorph == node.getGenericPolymorphicSpecialization()) { - cachedExecute.getModifiers().add(ABSTRACT); - } else { - SpecializationData genericPolymorph = node.getGenericPolymorphicSpecialization(); - CodeTreeBuilder builder = cachedExecute.createBuilder(); - ExecutableTypeData genericExecutable = new ExecutableTypeData(genericPolymorph, genericPolymorphMethod, node.getTypeSystem(), genericPolymorph.getReturnType().getTypeSystemType()); - ExecutableTypeData specificExecutable = new ExecutableTypeData(polymorph, cachedExecute, node.getTypeSystem(), polymorph.getReturnType().getTypeSystemType()); - builder.tree(createCastingExecute(builder, polymorph, specificExecutable, genericExecutable)); - } - return cachedExecute; } @@ -1271,7 +1281,7 @@ public CodeTree create(CodeTreeBuilder b, SpecializationData current) { return createGenericInvokeAndSpecialize(b, node.getGenericSpecialization(), current, currentNodeVar); } - }, null, false, true)); + }, null, false, true, false)); boolean firstUnreachable = true; for (SpecializationData current : node.getSpecializations()) { @@ -1305,8 +1315,9 @@ TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_GENERIC_NAME); - method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath())); - + if (!node.getGenericSpecialization().hasFrame(getContext())) { + method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath())); + } addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(), false); final CodeTreeBuilder builder = method.createBuilder(); @@ -1315,7 +1326,7 @@ public CodeTree create(CodeTreeBuilder b, SpecializationData current) { return createGenericInvoke(builder, current.getNode().getGenericSpecialization(), current); } - }, null, false, true)); + }, null, false, true, false)); emitUnreachableSpecializations(builder, node); @@ -1332,7 +1343,7 @@ } protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final boolean checkMinimumState, - final CodeBlock<SpecializationData> guardedblock, final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions) { + final CodeBlock<SpecializationData> guardedblock, final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions, final boolean typedCasts) { return guard(outerParent, source, group, checkMinimumState, new CodeBlock<Integer>() { public CodeTree create(CodeTreeBuilder parent, Integer ifCount) { @@ -1345,20 +1356,20 @@ } else { for (SpecializationGroup childGroup : group.getChildren()) { - builder.tree(createExecuteTree(builder, source, childGroup, checkMinimumState, guardedblock, null, false, emitAssumptions)); + builder.tree(createExecuteTree(builder, source, childGroup, checkMinimumState, guardedblock, null, false, emitAssumptions, typedCasts)); } } return builder.getRoot(); } - }, elseBlock, forceElse, emitAssumptions); + }, elseBlock, forceElse, emitAssumptions, typedCasts); } private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, CodeBlock<Integer> bodyBlock, CodeTree elseBlock, - boolean forceElse, boolean emitAssumptions) { + boolean forceElse, boolean emitAssumptions, boolean typedCasts) { CodeTreeBuilder builder = parent.create(); - int ifCount = emitGuards(builder, source, group, checkMinimumState, emitAssumptions); + int ifCount = emitGuards(builder, source, group, checkMinimumState, emitAssumptions, typedCasts); if (isReachableGroup(group, ifCount, checkMinimumState)) { builder.tree(bodyBlock.create(builder, ifCount)); @@ -1380,7 +1391,7 @@ return true; } SpecializationGroup previous = group.getPreviousGroup(); - if (previous == null || previous.getElseConnectableGuards().isEmpty()) { + if (previous == null || previous.findElseConnectableGuards(checkMinimumState).isEmpty()) { return true; } @@ -1396,7 +1407,7 @@ return true; } - private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, boolean emitAssumptions) { + private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, boolean emitAssumptions, boolean typedCasts) { NodeData node = source.getNode(); CodeTreeBuilder guardsBuilder = builder.create(); @@ -1406,30 +1417,11 @@ String guardsAnd = ""; String guardsCastAnd = ""; - List<GuardData> elseGuards = group.getElseConnectableGuards(); - boolean minimumState = checkMinimumState; if (minimumState) { - int groupMaxIndex = group.getMaxSpecializationIndex(); - - int genericIndex = node.getSpecializations().indexOf(node.getGenericSpecialization()); - if (groupMaxIndex >= genericIndex) { - // no minimum state check for an generic index - minimumState = false; - } - - if (minimumState) { - // no minimum state check if alread checked by parent group - int parentMaxIndex = -1; - if (group.getParent() != null) { - parentMaxIndex = group.getParent().getMaxSpecializationIndex(); - } - if (groupMaxIndex == parentMaxIndex) { - minimumState = false; - } - } - - if (minimumState) { + int groupMaxIndex = group.getUncheckedSpecializationIndex(); + + if (groupMaxIndex > -1) { guardsBuilder.string(guardsAnd); guardsBuilder.string("minimumState < " + groupMaxIndex); guardsAnd = " && "; @@ -1466,18 +1458,19 @@ throw new IllegalStateException(); } - CodeTree implicitGuard = createTypeGuard(guardsBuilder, child, valueParam, typeGuard.getType()); + CodeTree implicitGuard = createTypeGuard(guardsBuilder, child, valueParam, typeGuard.getType(), typedCasts); if (implicitGuard != null) { guardsBuilder.string(guardsAnd); guardsBuilder.tree(implicitGuard); guardsAnd = " && "; } - CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType(), checkMinimumState); + CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType(), checkMinimumState, typedCasts); if (cast != null) { castBuilder.tree(cast); } } + List<GuardData> elseGuards = group.findElseConnectableGuards(checkMinimumState); for (GuardData guard : group.getGuards()) { if (elseGuards.contains(guard)) { @@ -1544,7 +1537,7 @@ return false; } - private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType) { + private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean typedCasts) { NodeData node = field.getNodeData(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); @@ -1566,15 +1559,22 @@ } String castMethodName; + String castTypeName = null; List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); if (types.size() > 1) { castMethodName = TypeSystemCodeGenerator.isImplicitTypeMethodName(targetType); + if (typedCasts) { + castTypeName = implicitTypeName(source); + } } else { castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType); } - startCallTypeSystemMethod(getContext(), builder, node, castMethodName); + startCallTypeSystemMethod(getContext(), builder, node.getTypeSystem(), castMethodName); builder.string(valueName(source)); + if (castTypeName != null) { + builder.string(castTypeName); + } builder.end().end(); // call if (field.isShortCircuit()) { @@ -1586,7 +1586,8 @@ return builder.getRoot(); } - private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean checkMinimumState) { + // TODO merge redundancies with #createTypeGuard + private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean checkMinimumState, boolean typedCasts) { NodeData node = field.getNodeData(); TypeData sourceType = source.getTypeSystemType(); @@ -1602,20 +1603,30 @@ } String castMethodName; + String castTypeName = null; List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); if (types.size() > 1) { castMethodName = TypeSystemCodeGenerator.asImplicitTypeMethodName(targetType); + if (typedCasts) { + castTypeName = implicitTypeName(source); + } } else { castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); } - CodeTree value = createCallTypeSystemMethod(context, parent, node, castMethodName, CodeTreeBuilder.singleString(valueName(source))); + List<CodeTree> args = new ArrayList<>(); + args.add(CodeTreeBuilder.singleString(valueName(source))); + if (castTypeName != null) { + args.add(CodeTreeBuilder.singleString(castTypeName)); + } + + CodeTree value = createCallTypeSystemMethod(context, parent, node, castMethodName, args.toArray(new CodeTree[0])); CodeTreeBuilder builder = parent.create(); builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, value)); if (checkMinimumState && types.size() > 1) { CodeTree castType = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.getImplicitClass(targetType), CodeTreeBuilder.singleString(valueName(source))); - builder.tree(createLazyAssignment(builder, typeName(source), getContext().getType(Class.class), condition, castType)); + builder.tree(createLazyAssignment(builder, implicitTypeName(source), getContext().getType(Class.class), condition, castType)); } return builder.getRoot(); @@ -1765,7 +1776,7 @@ NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); if (types.size() > 1) { - replaceCall.string(typeName(param)); + replaceCall.string(implicitTypeName(param)); } } replaceCall.end().end(); @@ -1897,7 +1908,7 @@ protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, ExecutableTypeData castedType, CodeTree value) { boolean hasUnexpected = castedType.hasUnexpectedValue(getContext()); - return createCastType(node, sourceType, castedType.getType(), hasUnexpected, value); + return createCastType(node.getTypeSystem(), sourceType, castedType.getType(), hasUnexpected, value); } protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters, @@ -1909,27 +1920,13 @@ if (!targetParameter.getSpecification().isSignature()) { continue; } - TypeData targetType = targetParameter.getTypeSystemType(); - ExecutableTypeData targetExecutable = null; - if (child != null) { - targetExecutable = child.findExecutableType(getContext(), targetType); - } - - if (targetExecutable == null) { - // TODO what to do? assertion? - continue; - } - - CodeTree executionExpressions = createExecutionExpresssions(builder, child, sourceExecutable, targetExecutable, targetParameter, unexpectedParameter); - - String targetVarName = valueName(targetParameter); - CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, targetVarName, specialization, sourceExecutable, targetExecutable, targetParameter, - isShortCircuit(child)); - CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, targetVarName, specialization, targetParameter, unexpectedParameter); + CodeTree executionExpressions = createExecuteChild(builder, child, sourceExecutable, targetParameter, unexpectedParameter); + CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, specialization, sourceExecutable, targetParameter, isShortCircuit(child), unexpectedParameter); + CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, specialization, targetParameter, unexpectedParameter); if (shortCircuitTree == executionExpressions) { if (containsNewLine(executionExpressions)) { - builder.declaration(sourceExecutable.getType().getPrimitiveType(), targetVarName); + builder.declaration(targetParameter.getType(), valueName(targetParameter)); builder.tree(shortCircuitTree); } else { builder.startStatement().type(targetParameter.getType()).string(" ").tree(shortCircuitTree).end(); @@ -1942,69 +1939,229 @@ return builder.getRoot(); } - private CodeTree createExecutionExpresssions(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ExecutableTypeData targetExecutable, ActualParameter param, - ActualParameter unexpectedParameter) { - CodeTreeBuilder builder = parent.create(); - - TypeData type = param.getTypeSystemType(); - List<TypeData> targetTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(type); - - if (targetTypes.size() > 1) { + private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeData type) { + ExecutableTypeData targetExecutable = child.findExecutableType(getContext(), type); + if (targetExecutable == null) { + targetExecutable = child.findAnyGenericExecutableType(getContext()); + } + return targetExecutable; + } + + private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ActualParameter targetParameter, ActualParameter unexpectedParameter) { + SpecializationData specialization = getModel(); + TreeSet<TypeData> possiblePolymorphicTypes = lookupPolymorphicTargetTypes(targetParameter); + if (specialization.isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null && possiblePolymorphicTypes.size() > 1) { + + CodeTreeBuilder builder = parent.create(); + boolean elseIf = false; - int index = 0; - for (TypeData typeData : targetTypes) { - if (index < targetTypes.size() - 1) { - elseIf = builder.startIf(elseIf); - builder.string(typeName(param)).string(" == ").typeLiteral(typeData.getPrimitiveType()); - builder.end(); - builder.startBlock(); - } else { - builder.startElseBlock(); + for (TypeData possiblePolymoprhicType : possiblePolymorphicTypes) { + if (possiblePolymoprhicType.isGeneric()) { + continue; } - - ExecutableTypeData implictExecutableTypeData = child.getNodeData().findExecutableType(typeData, targetExecutable.getEvaluatedCount()); - ImplicitCastData cast = child.getNodeData().getTypeSystem().lookupCast(typeData, param.getTypeSystemType()); - CodeTree execute = createExecuteExpression(parent, child, sourceExecutable, implictExecutableTypeData, param, unexpectedParameter, cast); - builder.statement(execute); + elseIf = builder.startIf(elseIf); + + ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); + TypeData sourceType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; + builder.string(polymorphicTypeName(targetParameter)).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType()); + builder.end().startBlock(); + builder.startStatement(); + builder.tree(createExecuteChildExpression(parent, child, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null)); + builder.end(); builder.end(); - index++; + } + + builder.startElseBlock(); + builder.startStatement().tree(createExecuteChildImplicit(parent, child, sourceExecutable, targetParameter, unexpectedParameter)).end(); + builder.end(); + + return builder.getRoot(); + } else { + return createExecuteChildImplicit(parent, child, sourceExecutable, targetParameter, unexpectedParameter); + } + } + + protected final TreeSet<TypeData> lookupPolymorphicTargetTypes(ActualParameter param) { + SpecializationData specialization = getModel(); + TreeSet<TypeData> possiblePolymorphicTypes = new TreeSet<>(); + for (SpecializationData otherSpecialization : specialization.getNode().getSpecializations()) { + if (!otherSpecialization.isSpecialized()) { + continue; + } + ActualParameter otherParameter = otherSpecialization.findParameter(param.getLocalName()); + if (otherParameter != null) { + possiblePolymorphicTypes.add(otherParameter.getTypeSystemType()); } + } + return possiblePolymorphicTypes; + } + + private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ActualParameter param, ActualParameter unexpectedParameter) { + CodeTreeBuilder builder = parent.create(); + ActualParameter sourceParameter = sourceExecutable.findParameter(param.getLocalName()); + String childExecuteName = createExecuteChildMethodName(param, sourceParameter != null); + if (childExecuteName != null) { + builder.string(valueName(param)); + builder.string(" = "); + builder.startCall(childExecuteName); + + for (ActualParameter parameters : sourceExecutable.getParameters()) { + if (parameters.getSpecification().isSignature()) { + continue; + } + builder.string(parameters.getLocalName()); + } + + if (sourceParameter != null) { + builder.string(valueNameEvaluated(sourceParameter)); + } + + builder.string(implicitTypeName(param)); + + builder.end(); } else { - builder.tree(createExecuteExpression(parent, child, sourceExecutable, targetExecutable, param, unexpectedParameter, null)); + List<TypeData> sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); + TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; + if (sourceTypes.size() > 1) { + builder.tree(createExecuteChildImplicitExpressions(parent, param, expectType)); + } else { + builder.tree(createExecuteChildExpression(parent, child, expectType, param, unexpectedParameter, null)); + } } return builder.getRoot(); } - private CodeTree createExecuteExpression(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ExecutableTypeData targetExecutable, - ActualParameter targetParameter, ActualParameter unexpectedParameter, ImplicitCastData cast) { + private String createExecuteChildMethodName(ActualParameter param, boolean expect) { + NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); + if (child.getExecuteWith().size() > 0) { + return null; + } + List<TypeData> sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); + if (sourceTypes.size() <= 1) { + return null; + } + String prefix = expect ? "expect" : "execute"; + return prefix + Utils.firstLetterUpperCase(child.getName()) + Utils.firstLetterUpperCase(Utils.getSimpleName(param.getType())) + param.getIndex(); + } + + private List<CodeExecutableElement> createExecuteChilds(ActualParameter param, Set<TypeData> expectTypes) { + CodeExecutableElement executeMethod = createExecuteChild(param, null); + if (executeMethod == null) { + return Collections.emptyList(); + } + List<CodeExecutableElement> childs = new ArrayList<>(); + childs.add(executeMethod); + + for (TypeData expectType : expectTypes) { + CodeExecutableElement method = createExecuteChild(param, expectType); + if (method != null) { + childs.add(method); + } + } + return childs; + } + + private CodeExecutableElement createExecuteChild(ActualParameter param, TypeData expectType) { + String childExecuteName = createExecuteChildMethodName(param, expectType != null); + if (childExecuteName == null) { + return null; + } + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, expectType != null ? STATIC : FINAL), param.getType(), childExecuteName); + method.getThrownTypes().add(getContext().getTruffleTypes().getUnexpectedValueException()); + method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); + if (expectType != null) { + method.addParameter(new CodeVariableElement(expectType.getPrimitiveType(), valueNameEvaluated(param))); + } + method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); + + CodeTreeBuilder builder = method.createBuilder(); + builder.declaration(param.getType(), valueName(param)); + builder.tree(createExecuteChildImplicitExpressions(builder, param, expectType)); + builder.startReturn().string(valueName(param)).end(); + + return method; + } + + private CodeTree createExecuteChildImplicitExpressions(CodeTreeBuilder parent, ActualParameter targetParameter, TypeData expectType) { + CodeTreeBuilder builder = parent.create(); + NodeData node = getModel().getNode(); + NodeChildData child = node.findChild(targetParameter.getSpecification().getName()); + List<TypeData> sourceTypes = node.getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType()); + boolean elseIf = false; + int index = 0; + for (TypeData sourceType : sourceTypes) { + if (index < sourceTypes.size() - 1) { + elseIf = builder.startIf(elseIf); + builder.string(implicitTypeName(targetParameter)).string(" == ").typeLiteral(sourceType.getPrimitiveType()); + builder.end(); + builder.startBlock(); + } else { + builder.startElseBlock(); + } + + ExecutableTypeData implictExecutableTypeData = child.findExecutableType(getContext(), sourceType); + if (implictExecutableTypeData == null) { + /* + * For children with executeWith.size() > 0 an executable type may not exist so + * use the generic executable type which is guaranteed to exist. An expect call + * is inserted automatically by #createExecuteExpression. + */ + implictExecutableTypeData = child.getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), child.getExecuteWith().size()); + } + + ImplicitCastData cast = child.getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType()); + CodeTree execute = createExecuteChildExpression(builder, child, expectType, targetParameter, null, cast); + builder.statement(execute); + builder.end(); + index++; + } + return builder.getRoot(); + } + + private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData child, TypeData sourceParameterType, ActualParameter targetParameter, ActualParameter unexpectedParameter, + ImplicitCastData cast) { + // assignments: targetType <- castTargetType <- castSourceType <- sourceType + TypeData sourceType = sourceParameterType; + TypeData targetType = targetParameter.getTypeSystemType(); + TypeData castSourceType = targetType; + TypeData castTargetType = targetType; + + if (cast != null) { + castSourceType = cast.getSourceType(); + castTargetType = cast.getTargetType(); + } + + CodeTree expression; + if (sourceType == null) { + ExecutableTypeData targetExecutable = resolveExecutableType(child, castSourceType); + expression = createExecuteChildExpression(parent, child, targetParameter, targetExecutable, unexpectedParameter); + sourceType = targetExecutable.getType(); + } else { + expression = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)); + } + + // target = expectTargetType(implicitCast(expectCastSourceType(source))) + TypeSystemData typeSystem = child.getNodeData().getTypeSystem(); + expression = createExpectType(typeSystem, sourceType, castSourceType, expression); + expression = createImplicitCast(parent, typeSystem, cast, expression); + expression = createExpectType(typeSystem, castTargetType, targetType, expression); + CodeTreeBuilder builder = parent.create(); builder.string(valueName(targetParameter)); builder.string(" = "); - if (cast != null) { - startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), cast.getMethodName()); - } - - if (targetExecutable.getType().needsCastTo(context, targetParameter.getTypeSystemType()) && cast == null) { - startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), TypeSystemCodeGenerator.expectTypeMethodName(targetParameter.getTypeSystemType())); + builder.tree(expression); + return builder.getRoot(); + } + + private CodeTree createImplicitCast(CodeTreeBuilder parent, TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) { + if (cast == null) { + return expression; } - - NodeData node = getModel().getNode(); - ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); - if (sourceParameter == null) { - builder.tree(createExecuteChildExpression(builder, child, targetParameter, targetExecutable, unexpectedParameter)); - } else { - CodeTree var = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)); - builder.tree(createExpectExecutableType(node, sourceParameter.getTypeSystemType(), targetExecutable, var)); - } - - if (targetExecutable.getType().needsCastTo(context, targetParameter.getTypeSystemType())) { - builder.end().end(); - } - - if (cast != null) { - builder.end().end(); - } - + CodeTreeBuilder builder = parent.create(); + startCallTypeSystemMethod(getContext(), builder, typeSystem, cast.getMethodName()); + builder.tree(expression); + builder.end().end(); return builder.getRoot(); } @@ -2021,49 +2178,67 @@ return false; } - private boolean hasUnexpected(ExecutableTypeData target, ActualParameter sourceParameter, ActualParameter targetParameter) { - List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType()); + private boolean hasUnexpected(ActualParameter sourceParameter, ActualParameter targetParameter, ActualParameter unexpectedParameter) { NodeChildData child = getModel().getNode().findChild(targetParameter.getSpecification().getName()); - boolean hasUnexpected = false; - for (TypeData type : types) { - if (hasUnexpected) { - continue; + + if (getModel().isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) { + // check for other polymorphic types + TreeSet<TypeData> polymorphicTargetTypes = lookupPolymorphicTargetTypes(targetParameter); + if (polymorphicTargetTypes.size() > 1) { + for (TypeData polymorphicTargetType : polymorphicTargetTypes) { + if (hasUnexpectedType(child, sourceParameter, polymorphicTargetType)) { + return true; + } + } } - ExecutableTypeData execTarget = target; - if (type != execTarget.getType()) { - execTarget = child.findExecutableType(getContext(), type); - } - hasUnexpected = hasUnexpected || hasUnexpectedType(execTarget, sourceParameter, type); } - return hasUnexpected; - } - - private boolean hasUnexpectedType(ExecutableTypeData target, ActualParameter sourceParameter, TypeData type) { - boolean targetCast = target.getType().needsCastTo(context, type); - if (targetCast && getModel().getNode().getTypeSystem().lookupCast(target.getType(), type) == null) { + + if (hasUnexpectedType(child, sourceParameter, targetParameter.getTypeSystemType())) { return true; } - if (sourceParameter == null) { - return target.hasUnexpectedValue(getContext()); - } else { - if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), type)) { - return target.hasUnexpectedValue(getContext()); + return false; + } + + private boolean hasUnexpectedType(NodeChildData child, ActualParameter sourceParameter, TypeData targetType) { + List<TypeData> implicitSourceTypes = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); + + for (TypeData implicitSourceType : implicitSourceTypes) { + TypeData sourceType; + ExecutableTypeData targetExecutable = resolveExecutableType(child, implicitSourceType); + if (sourceParameter != null) { + sourceType = sourceParameter.getTypeSystemType(); + } else { + if (targetExecutable.hasUnexpectedValue(getContext())) { + return true; + } + sourceType = targetExecutable.getType(); } - return false; + + ImplicitCastData cast = getModel().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType); + if (cast != null) { + if (cast.getSourceType().needsCastTo(getContext(), targetType)) { + return true; + } + } + + if (sourceType.needsCastTo(getContext(), targetType)) { + return true; + } } + return false; } - private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ExecutableTypeData currentExecutable, - ExecutableTypeData targetExecutable, ActualParameter param, boolean shortCircuit) { + private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ExecutableTypeData currentExecutable, ActualParameter param, + boolean shortCircuit, ActualParameter unexpectedParameter) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); ActualParameter sourceParameter = currentExecutable.findParameter(param.getLocalName()); - boolean unexpected = hasUnexpected(targetExecutable, sourceParameter, param); + boolean unexpected = hasUnexpected(sourceParameter, param, unexpectedParameter); if (!unexpected) { return body; } if (!shortCircuit) { - builder.declaration(param.getType(), targetVariableName); + builder.declaration(param.getType(), valueName(param)); } builder.startTryBlock(); @@ -2078,7 +2253,6 @@ ActualParameter genericParameter = generic.findParameter(param.getLocalName()); List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter); - builder.tree(createDeoptimize(builder)); builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter)); if (specialization.isPolymorphic()) { builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param)); @@ -2097,6 +2271,8 @@ SpecializationData generic = node.getGenericPolymorphicSpecialization(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); + builder.startStatement().string(polymorphicTypeName(param)).string(" = ").typeLiteral(getContext().getType(Object.class)).end(); + builder.startReturn(); CodeTreeBuilder execute = new CodeTreeBuilder(builder); @@ -2186,8 +2362,7 @@ return builder.getRoot(); } - private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ActualParameter parameter, - ActualParameter exceptionParam) { + private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) { NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName()); if (!isShortCircuit(forField)) { return body; @@ -2196,7 +2371,7 @@ CodeTreeBuilder builder = new CodeTreeBuilder(parent); ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter); builder.tree(createShortCircuitValue(builder, specialization, forField, shortCircuitParam, exceptionParam)); - builder.declaration(parameter.getType(), targetVariableName, CodeTreeBuilder.createBuilder().defaultValue(parameter.getType())); + builder.declaration(parameter.getType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getType())); builder.startIf().string(shortCircuitParam.getLocalName()).end(); builder.startBlock(); @@ -2260,32 +2435,78 @@ return builder.getRoot(); } + + protected final CodeExecutableElement createUpdateTypes(TypeMirror polymorphicType) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), UPDATE_TYPES_NAME); + method.getParameters().add(new CodeVariableElement(polymorphicType, "polymorphic")); + CodeTreeBuilder builder = method.createBuilder(); + + if (getModel().isPolymorphic()) { + builder.startStatement(); + builder.startCall("next0", "updateTypes").string("polymorphic").end(); + builder.end(); + } else if (getModel().isSpecialized()) { + for (ActualParameter parameter : getModel().getParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; + } + if (lookupPolymorphicTargetTypes(parameter).size() <= 1) { + continue; + } + builder.startStatement(); + builder.startCall("polymorphic", createUpdateTypeName(parameter)); + builder.typeLiteral(parameter.getType()); + builder.end().end(); + } + + builder.startStatement().startCall("super", UPDATE_TYPES_NAME).string("polymorphic").end().end(); + } + return method; + } + + protected String createUpdateTypeName(ActualParameter parameter) { + return "update" + Utils.firstLetterUpperCase(parameter.getLocalName()) + "Type"; + } } private class PolymorphicNodeFactory extends SpecializedNodeFactory { - private final boolean generic; - - public PolymorphicNodeFactory(ProcessorContext context, CodeTypeElement nodeGen, boolean generic) { + public PolymorphicNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) { super(context, nodeGen); - this.generic = generic; } @Override - public CodeTypeElement create(SpecializationData specialization) { - NodeData node = specialization.getNode(); + public CodeTypeElement create(SpecializationData polymorph) { + NodeData node = polymorph.getNode(); TypeMirror baseType = node.getNodeType(); if (nodeGen != null) { baseType = nodeGen.asType(); } - CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC), nodePolymorphicClassName(node, specialization), baseType, false); - - if (!generic) { - clazz.getModifiers().add(Modifier.FINAL); - } + CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node, polymorph), baseType, false); clazz.getAnnotationMirrors().add(createNodeInfo(node, Kind.POLYMORPHIC)); + for (ActualParameter polymorphParameter : polymorph.getParameters()) { + if (!polymorphParameter.getSpecification().isSignature()) { + continue; + } + if (!polymorphParameter.getTypeSystemType().isGeneric()) { + continue; + } + Set<TypeData> types = new HashSet<>(); + for (SpecializationData specialization : node.getSpecializations()) { + if (!specialization.isSpecialized()) { + continue; + } + ActualParameter parameter = specialization.findParameter(polymorphParameter.getLocalName()); + assert parameter != null; + types.add(parameter.getTypeSystemType()); + } + CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), getContext().getType(Class.class), polymorphicTypeName(polymorphParameter)); + var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getCompilationFinal())); + clazz.add(var); + } + return clazz; } @@ -2296,273 +2517,39 @@ createConstructors(clazz); createExecuteMethods(specialization); - if (generic) { - getElement().add(createOptimizeTypes()); - createCachedExecuteMethods(specialization); - createIsCompatible(clazz, specialization); - } - } - - private CodeExecutableElement createOptimizeTypes() { - NodeData node = getModel().getNode(); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), getContext().getType(void.class), "optimizeTypes"); - CodeTreeBuilder builder = method.createBuilder(); - - boolean elseIf = false; - for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) { - String className = nodePolymorphicClassName(node, polymorphic); - - String sep = ""; - StringBuilder reason = new StringBuilder("Optimized polymorphic types for ("); - for (ActualParameter parameter : polymorphic.getReturnTypeAndParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - reason.append(sep).append(Utils.getSimpleName(parameter.getType())); - sep = ", "; + getElement().add(createUpdateTypes(nodeGen.asType())); + + for (ActualParameter parameter : specialization.getParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; } - reason.append(")"); - - elseIf = builder.startIf(elseIf); - builder.startCall("isCompatible0"); - builder.startGroup().string(className).string(".class").end(); - builder.end().end().startBlock(); - - builder.startStatement().startCall("super", "replace"); - builder.startNew(className).string("this").end(); - builder.doubleQuote(reason.toString()); - builder.end().end(); // call - builder.end(); - } - return method; - } - } - - private class BaseCastNodeFactory extends ClassElementFactory<NodeData> { - - protected final Set<TypeData> usedTargetTypes; - - public BaseCastNodeFactory(ProcessorContext context, Set<TypeData> usedTargetTypes) { - super(context); - this.usedTargetTypes = usedTargetTypes; - } - - @Override - protected CodeTypeElement create(NodeData m) { - CodeTypeElement type = createClass(m, modifiers(STATIC), nodeCastClassName(m, null), context.getTruffleTypes().getNode(), false); - - CodeVariableElement delegate = new CodeVariableElement(m.getNodeType(), "delegate"); - delegate.getModifiers().add(PROTECTED); - delegate.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation())); - - type.add(delegate); - type.add(createConstructorUsingFields(modifiers(), type)); - return type; - } - - @Override - protected void createChildren(NodeData m) { - CodeTypeElement type = getElement(); - type.add(createExecute(EXECUTE_SPECIALIZE_NAME, true)); - type.add(createExecute(EXECUTE_GENERIC_NAME, false)); - - for (ExecutableTypeData targetExecutable : m.getExecutableTypes()) { - if (!usedTargetTypes.contains(targetExecutable.getType()) && targetExecutable.hasUnexpectedValue(getContext())) { + if (lookupPolymorphicTargetTypes(parameter).size() <= 1) { continue; } - CodeExecutableElement execute = createCastExecute(targetExecutable, targetExecutable, false); - CodeExecutableElement expect = createCastExecute(targetExecutable, targetExecutable, true); - if (execute != null) { - getElement().add(execute); - } - if (expect != null) { - getElement().add(expect); - } - } - Set<TypeData> sourceTypes = new TreeSet<>(); - List<ImplicitCastData> casts = getModel().getTypeSystem().getImplicitCasts(); - for (ImplicitCastData cast : casts) { - sourceTypes.add(cast.getSourceType()); - } - - CodeTypeElement baseType = getElement(); - for (TypeData sourceType : sourceTypes) { - add(new SpecializedCastNodeFactory(context, baseType, sourceType, usedTargetTypes), getModel()); - } - } - - private CodeExecutableElement createExecute(String name, boolean specialize) { - NodeData node = getModel(); - TypeMirror objectType = node.getTypeSystem().getGenericType(); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), objectType, name, new CodeVariableElement(objectType, "value")); - if (specialize) { - method.getModifiers().add(FINAL); + getElement().add(createUpdateType(parameter)); } + + createCachedExecuteMethods(specialization); + + } + + private ExecutableElement createUpdateType(ActualParameter parameter) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), createUpdateTypeName(parameter)); + method.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), "type")); CodeTreeBuilder builder = method.createBuilder(); - List<ImplicitCastData> casts = node.getTypeSystem().getImplicitCasts(); - boolean elseIf = false; - for (ImplicitCastData cast : casts) { - elseIf = builder.startIf(elseIf); - startCallTypeSystemMethod(context, builder, getModel(), TypeSystemCodeGenerator.isTypeMethodName(cast.getSourceType())); - builder.string("value"); - builder.end().end(); - builder.end(); - builder.startBlock(); - - if (specialize) { - builder.startStatement().startCall("replace").startNew(nodeCastClassName(getModel(), cast.getSourceType())).string("delegate").end().doubleQuote("Added cast").end().end(); - } - builder.startReturn(); - - startCallTypeSystemMethod(context, builder, getModel(), cast.getMethodName()); - startCallTypeSystemMethod(context, builder, getModel(), TypeSystemCodeGenerator.asTypeMethodName(cast.getSourceType())); - builder.string("value"); - builder.end().end(); - builder.end().end(); - - builder.end(); - builder.end(); - } - - builder.startReturn().string("value").end(); + String fieldName = polymorphicTypeName(parameter); + builder.startIf().string(fieldName).isNull().end().startBlock(); + builder.startStatement().string(fieldName).string(" = ").string("type").end(); + builder.end(); + builder.startElseIf().string(fieldName).string(" != ").string("type").end(); + builder.startBlock(); + builder.startStatement().string(fieldName).string(" = ").typeLiteral(getContext().getType(Object.class)).end(); + builder.end(); return method; } - protected CodeExecutableElement createCastExecute(ExecutableTypeData sourceExecutable, ExecutableTypeData targetExecutable, boolean expect) { - ImplicitCastData cast = null; - if (!sourceExecutable.getType().equals(targetExecutable.getType())) { - cast = getModel().getTypeSystem().lookupCast(sourceExecutable.getType(), targetExecutable.getType()); - if (cast == null) { - return null; - } - } - - if (expect) { - if (targetExecutable.getEvaluatedCount() > 0) { - return null; - } else if (Utils.isObject(targetExecutable.getType().getPrimitiveType())) { - return null; - } - } - - boolean hasTargetUnexpected = targetExecutable.hasUnexpectedValue(getContext()); - boolean hasSourceUnexpected = sourceExecutable.hasUnexpectedValue(getContext()); - - CodeExecutableElement method = copyTemplateMethod(targetExecutable); - method.getModifiers().add(PUBLIC); - - CodeTreeBuilder builder = method.createBuilder(); - - if (hasSourceUnexpected && cast != null) { - builder.startTryBlock(); - } - - if (expect) { - method.getParameters().clear(); - String expectMethodName; - if (hasTargetUnexpected) { - expectMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetExecutable.getType()); - } else { - expectMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetExecutable.getType()); - } - method.setSimpleName(CodeNames.of(expectMethodName)); - method.addParameter(new CodeVariableElement(getModel().getTypeSystem().getGenericType(), "value")); - } - - builder.startReturn(); - CodeTree executeCall; - if (expect) { - executeCall = createCastType(getModel(), getModel().getTypeSystem().getGenericTypeData(), sourceExecutable.getType(), hasSourceUnexpected, CodeTreeBuilder.singleString("value")); - } else { - executeCall = createTemplateMethodCall(builder, CodeTreeBuilder.singleString("delegate."), targetExecutable, sourceExecutable, null); - } - if (cast != null) { - startCallTypeSystemMethod(context, builder, getModel(), cast.getMethodName()); - builder.tree(executeCall); - builder.end().end(); - } else { - builder.tree(executeCall); - } - builder.end(); - - if (hasSourceUnexpected && cast != null) { - builder.end(); - builder.startCatchBlock(getContext().getTruffleTypes().getUnexpectedValueException(), "ex"); - builder.startStatement().startCall("replace").startNew(nodeCastClassName(getModel(), null)).string("delegate").end().doubleQuote("Removed cast").end().end(); - - if (hasTargetUnexpected) { - builder.startThrow().string("ex").end(); - } else { - builder.startThrow().startNew(getContext().getType(AssertionError.class)).end().end(); - } - builder.end(); - } - - return method; - } - - private CodeExecutableElement copyTemplateMethod(TemplateMethod targetExecutable) { - CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), targetExecutable.getMethod()); - method.getModifiers().remove(ABSTRACT); - method.getAnnotationMirrors().clear(); - Modifier visibility = Utils.getVisibility(method.getModifiers()); - if (visibility != null) { - method.getModifiers().remove(visibility); - } - int index = 0; - for (ActualParameter parameter : targetExecutable.getParameters()) { - ((CodeVariableElement) method.getParameters().get(index)).setName(parameter.getLocalName()); - index++; - } - return method; - } - - } - - private class SpecializedCastNodeFactory extends BaseCastNodeFactory { - - private final CodeTypeElement baseType; - private final TypeData sourceType; - - public SpecializedCastNodeFactory(ProcessorContext context, CodeTypeElement baseType, TypeData type, Set<TypeData> usedTargetTypes) { - super(context, usedTargetTypes); - this.baseType = baseType; - this.sourceType = type; - } - - @Override - protected CodeTypeElement create(NodeData m) { - CodeTypeElement type = createClass(m, modifiers(PRIVATE, STATIC, FINAL), nodeCastClassName(m, sourceType), baseType.asType(), false); - type.add(createConstructorUsingFields(modifiers(), type)); - return type; - } - - @Override - protected void createChildren(NodeData node) { - for (TypeData targetType : usedTargetTypes) { - for (ExecutableTypeData targetExecutable : node.getExecutableTypes()) { - if (targetExecutable.getType().equals(targetType)) { - ExecutableTypeData sourceExecutable = node.findExecutableType(sourceType, targetExecutable.getEvaluatedCount()); - if (sourceExecutable == null) { - // TODO what if there is no evaluated version? - continue; - } - CodeExecutableElement execute = createCastExecute(sourceExecutable, targetExecutable, false); - CodeExecutableElement expect = createCastExecute(sourceExecutable, targetExecutable, true); - if (execute != null) { - getElement().add(execute); - } - if (expect != null) { - getElement().add(expect); - } - } - } - - } - } - } private class SpecializedNodeFactory extends NodeBaseFactory { @@ -2615,14 +2602,11 @@ CodeTypeElement clazz = getElement(); createConstructors(clazz); - NodeData node = specialization.getNode(); - - if (node.needsRewrites(getContext()) && node.isPolymorphic()) { - createIsCompatible(clazz, specialization); - } - createExecuteMethods(specialization); createCachedExecuteMethods(specialization); + if (specialization.getNode().isPolymorphic()) { + getElement().add(createUpdateTypes(nodeGen.asType())); + } } protected void createConstructors(CodeTypeElement clazz) { @@ -2659,11 +2643,11 @@ NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); if (types.size() > 1) { - clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), typeName(param))); - superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), typeName(param))); + clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param))); + superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); builder.startStatement(); - builder.string("this.").string(typeName(param)).string(" = ").string(typeName(param)); + builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param)); builder.end(); } } @@ -2695,39 +2679,45 @@ protected void createCachedExecuteMethods(SpecializationData specialization) { NodeData node = specialization.getNode(); + if (!node.isPolymorphic()) { + return; + } + CodeTypeElement clazz = getElement(); - for (final SpecializationData polymorphic : node.getPolymorphicSpecializations()) { - if (!specialization.getSignature().isCompatibleTo(polymorphic.getSignature())) { - continue; - } - ExecutableElement executeCached = nodeGen.getMethod(executeCachedName(polymorphic)); - ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached, node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType()); - - CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, false); - CodeTreeBuilder builder = executeMethod.createBuilder(); - - if (specialization.isGeneric() || specialization.isPolymorphic()) { - builder.startThrow().startNew(getContext().getType(AssertionError.class)); - builder.doubleQuote("Should not be reached."); - builder.end().end(); - } else if (specialization.isUninitialized()) { - builder.tree(createAppendPolymorphic(builder, specialization)); - } else { - CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); - elseBuilder.startReturn().startCall("this.next0", executeCachedName(polymorphic)); - addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true, null); - elseBuilder.end().end(); - - boolean forceElse = specialization.getExceptions().size() > 0; - builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() { - - public CodeTree create(CodeTreeBuilder b, SpecializationData current) { - return createGenericInvoke(b, polymorphic, current); - } - }, elseBuilder.getRoot(), forceElse, true)); - } - clazz.add(executeMethod); + + final SpecializationData polymorphic = node.getGenericPolymorphicSpecialization(); + + ExecutableElement executeCached = nodeGen.getMethod(executeCachedName(polymorphic)); +// ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached, +// node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType()); + + ExecutableTypeMethodParser parser = new ExecutableTypeMethodParser(getContext(), node); + ExecutableTypeData execType = parser.parse(Arrays.asList(executeCached)).get(0); + + CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, false); + CodeTreeBuilder builder = executeMethod.createBuilder(); + + if (specialization.isGeneric() || specialization.isPolymorphic()) { + builder.startThrow().startNew(getContext().getType(AssertionError.class)); + builder.doubleQuote("Should not be reached."); + builder.end().end(); + } else if (specialization.isUninitialized()) { + builder.tree(createAppendPolymorphic(builder, specialization)); + } else { + CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); + elseBuilder.startReturn().startCall("this.next0", executeCachedName(polymorphic)); + addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true, null); + elseBuilder.end().end(); + + boolean forceElse = specialization.getExceptions().size() > 0; + builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() { + + public CodeTree create(CodeTreeBuilder b, SpecializationData current) { + return createGenericInvoke(b, polymorphic, current); + } + }, elseBuilder.getRoot(), forceElse, true, true)); } + clazz.add(executeMethod); } private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) { @@ -2763,8 +2753,9 @@ builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot()); + CodeTree root = builder.create().cast(nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).string("root").getRoot(); builder.startIf().string("this.next0 != null").end().startBlock(); - builder.startStatement().string("(").cast(nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).string("root).optimizeTypes()").end(); + builder.startStatement().string("(").tree(root).string(").").startCall(UPDATE_TYPES_NAME).tree(root).end().end(); builder.end(); if (Utils.isVoid(builder.findMethod().getReturnType())) { @@ -2880,7 +2871,7 @@ public CodeTree create(CodeTreeBuilder b, SpecializationData current) { return createExecute(b, executable, specialization); } - }, returnSpecialized, false, false)); + }, returnSpecialized, false, false, false)); return builder.getRoot(); }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Tue Oct 15 21:28:24 2013 +0200 @@ -223,62 +223,44 @@ return; } - Signature genericSignature = node.getGenericSpecialization().getSignature(); - Set<Signature> signatures = new TreeSet<>(); + SpecializationData generic = node.getGenericSpecialization(); - for (SpecializationData specialization1 : node.getSpecializations()) { - Signature signature = specialization1.getSignature(); + List<TypeData> polymorphicSignature = new ArrayList<>(); + // TODO we should support more optimized for boxing +// List<ActualParameter> updatePolymorphic = generic.getReturnTypeAndParameters(); + List<ActualParameter> updatePolymorphic = Arrays.asList(); + for (ActualParameter genericParameter : updatePolymorphic) { + if (!genericParameter.getSpecification().isSignature()) { + continue; + } - for (SpecializationData specialization2 : node.getSpecializations()) { - if (specialization1 == specialization2) { + Set<TypeData> usedTypes = new HashSet<>(); + for (SpecializationData specialization : node.getSpecializations()) { + if (!specialization.isSpecialized()) { continue; } - signatures.add(signature.combine(genericSignature, specialization2.getSignature())); + ActualParameter parameter = specialization.findParameter(genericParameter.getLocalName()); + if (parameter == null) { + throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName()); + } + usedTypes.add(parameter.getTypeSystemType()); } + + TypeData polymorphicType; + if (usedTypes.size() == 1) { + polymorphicType = usedTypes.iterator().next(); + } else { + polymorphicType = node.getTypeSystem().getGenericTypeData(); + } + polymorphicSignature.add(polymorphicType); } - while (true) { - List<Signature> newSignatures = new ArrayList<>(); - for (Signature signature1 : signatures) { - for (Signature signature2 : signatures) { - if (signature1 == signature2) { - continue; - } - newSignatures.add(signature1.combine(genericSignature, signature2)); - } - } - if (!signatures.addAll(newSignatures)) { - break; - } - } - - List<Signature> sortedSignatures = new ArrayList<>(signatures); - - SpecializationData polymorphicGeneric = null; - List<SpecializationData> specializations = new ArrayList<>(); - SpecializationData generic = node.getGenericSpecialization(); - for (Signature signature : sortedSignatures) { - SpecializationData specialization = new SpecializationData(generic, false, false, true); - - for (Iterator<ActualParameter> iterator = specialization.getParameters().iterator(); iterator.hasNext();) { - ActualParameter param = iterator.next(); - if (param.getSpecification().isLocal()) { - iterator.remove(); - } - } - - specialization.forceFrame(context.getTruffleTypes().getFrame()); - specialization.setNode(node); - specialization.updateSignature(signature); - specializations.add(specialization); - - if (genericSignature.equals(signature)) { - polymorphicGeneric = specialization; - } - } - - node.setGenericPolymorphicSpecialization(polymorphicGeneric); - node.setPolymorphicSpecializations(specializations); + SpecializationData specialization = new SpecializationData(generic, false, false, true); + specialization.updateSignature(new Signature(polymorphicSignature)); + specialization.setNode(node); + node.setGenericPolymorphicSpecialization(specialization); + // TODO remove polymoprhic specializations + node.setPolymorphicSpecializations(Collections.<SpecializationData> emptyList()); } private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List<? extends Element> elements, List<TypeElement> typeHierarchy) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java Tue Oct 15 21:28:24 2013 +0200 @@ -188,6 +188,10 @@ return order; } + public boolean isSpecialized() { + return !isGeneric() && !isUninitialized() && !isPolymorphic(); + } + public boolean isGeneric() { return generic; } @@ -268,4 +272,13 @@ } return false; } + + public boolean hasFrame(ProcessorContext context) { + for (ActualParameter param : getParameters()) { + if (Utils.typeEquals(param.getType(), context.getTruffleTypes().getFrame())) { + return true; + } + } + return false; + } }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java Tue Oct 15 21:28:24 2013 +0200 @@ -90,7 +90,14 @@ return null; } - public List<GuardData> getElseConnectableGuards() { + public List<GuardData> findElseConnectableGuards(boolean minimumStateCheck) { + if (minimumStateCheck) { + /* + * TODO investigate further if we really cannot else connect guards if minimum state is + * required + */ + return Collections.emptyList(); + } if (!getTypeGuards().isEmpty() || !getAssumptions().isEmpty()) { return Collections.emptyList(); } @@ -101,7 +108,7 @@ List<GuardData> elseConnectableGuards = new ArrayList<>(); int guardIndex = 0; - while (guardIndex < getGuards().size() && findNegatedGuardInPrevious(getGuards().get(guardIndex)) != null) { + while (guardIndex < getGuards().size() && findNegatedGuardInPrevious(getGuards().get(guardIndex), minimumStateCheck) != null) { elseConnectableGuards.add(getGuards().get(guardIndex)); guardIndex++; } @@ -109,17 +116,18 @@ return elseConnectableGuards; } - private GuardData findNegatedGuardInPrevious(GuardData guard) { + private GuardData findNegatedGuardInPrevious(GuardData guard, boolean minimumStateCheck) { SpecializationGroup previous = this.getPreviousGroup(); if (previous == null) { return null; } - List<GuardData> elseConnectedGuards = previous.getElseConnectableGuards(); + List<GuardData> elseConnectedGuards = previous.findElseConnectableGuards(minimumStateCheck); if (previous == null || previous.getGuards().size() != elseConnectedGuards.size() + 1) { return null; } + /* Guard is else branch can be connected in previous specialization. */ if (elseConnectedGuards.contains(guard)) { return guard; } @@ -341,6 +349,28 @@ return parent.children.get(index - 1); } + public int getUncheckedSpecializationIndex() { + int groupMaxIndex = getMaxSpecializationIndex(); + + int genericIndex = node.getSpecializations().indexOf(node.getGenericSpecialization()); + if (groupMaxIndex >= genericIndex) { + // no minimum state check for an generic index + groupMaxIndex = -1; + } + + if (groupMaxIndex > -1) { + // no minimum state check if already checked by parent group + int parentMaxIndex = -1; + if (getParent() != null) { + parentMaxIndex = getParent().getMaxSpecializationIndex(); + } + if (groupMaxIndex == parentMaxIndex) { + groupMaxIndex = -1; + } + } + return groupMaxIndex; + } + public int getMaxSpecializationIndex() { if (specialization != null) { return specialization.getNode().getSpecializations().indexOf(specialization);
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java Tue Oct 15 21:28:24 2013 +0200 @@ -237,6 +237,9 @@ if (!parameter.getSpecification().isSignature()) { continue; } + if (signatureIndex >= signature.size()) { + break; + } TypeData newType = signature.get(signatureIndex++); if (!parameter.getTypeSystemType().equals(newType)) { replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, newType));
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java Tue Oct 15 21:28:24 2013 +0200 @@ -97,35 +97,18 @@ for (TypeData type : typeSystem.getTypes()) { if (!type.isGeneric()) { - CodeExecutableElement isType = createIsTypeMethod(type); - if (isType != null) { - clazz.add(isType); - } - CodeExecutableElement asType = createAsTypeMethod(type); - if (asType != null) { - clazz.add(asType); - } + clazz.addOptional(createIsTypeMethod(type)); + clazz.addOptional(createAsTypeMethod(type)); for (TypeData sourceType : collectExpectSourceTypes(type)) { - CodeExecutableElement expect = createExpectTypeMethod(type, sourceType); - if (expect != null) { - clazz.add(expect); - } + clazz.addOptional(createExpectTypeMethod(type, sourceType)); } - CodeExecutableElement asImplicit = createAsImplicitTypeMethod(type); - if (asImplicit != null) { - clazz.add(asImplicit); - } - CodeExecutableElement isImplicit = createIsImplicitTypeMethod(type); - if (isImplicit != null) { - clazz.add(isImplicit); - } - - CodeExecutableElement typeIndex = createGetTypeIndex(type); - if (typeIndex != null) { - clazz.add(typeIndex); - } + clazz.addOptional(createAsImplicitTypeMethod(type, true)); + clazz.addOptional(createAsImplicitTypeMethod(type, false)); + clazz.addOptional(createIsImplicitTypeMethod(type, true)); + clazz.addOptional(createIsImplicitTypeMethod(type, false)); + clazz.addOptional(createGetTypeIndex(type)); } } @@ -159,7 +142,7 @@ return field; } - private CodeExecutableElement createIsImplicitTypeMethod(TypeData type) { + private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) { TypeSystemData typeSystem = getModel(); List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type); if (casts.isEmpty()) { @@ -167,6 +150,9 @@ } CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type)); method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); + if (typed) { + method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint")); + } CodeTreeBuilder builder = method.createBuilder(); List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type); @@ -175,14 +161,27 @@ String sep = ""; for (TypeData sourceType : sourceTypes) { builder.string(sep); + if (typed) { + builder.string("(typeHint == ").typeLiteral(sourceType.getPrimitiveType()).string(" && "); + } builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); + if (typed) { + builder.string(")"); + } + if (sourceTypes.lastIndexOf(sourceType) != sourceTypes.size() - 1) { + builder.newLine(); + } + if (sep.equals("")) { + builder.startIndention(); + } sep = " || "; } builder.end(); + builder.end(); return method; } - private CodeExecutableElement createAsImplicitTypeMethod(TypeData type) { + private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean typed) { TypeSystemData typeSystem = getModel(); List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type); if (casts.isEmpty()) { @@ -190,6 +189,9 @@ } CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asImplicitTypeMethodName(type)); method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); + if (typed) { + method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint")); + } List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type); @@ -197,7 +199,12 @@ boolean elseIf = false; for (TypeData sourceType : sourceTypes) { elseIf = builder.startIf(elseIf); - builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); + if (typed) { + builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType()); + } else { + builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end(); + } + builder.end().startBlock(); builder.startReturn();
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java Tue Oct 15 21:28:24 2013 +0200 @@ -63,7 +63,7 @@ } public TypedNode createStringLiteral(String value) { - return StringLiteralNodeFactory.create(value); + return new StringLiteralNode(value); } public StatementNode createAssignment(String name, TypedNode right) { @@ -112,9 +112,9 @@ public TypedNode createNumericLiteral(String value) { try { - return IntegerLiteralNodeFactory.create(Integer.parseInt(value)); + return new IntegerLiteralNode(Integer.parseInt(value)); } catch (NumberFormatException ex) { - return BigIntegerLiteralNodeFactory.create(new BigInteger(value)); + return new BigIntegerLiteralNode(new BigInteger(value)); } }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java Tue Oct 15 21:28:24 2013 +0200 @@ -46,32 +46,9 @@ } } - @TypeCheck - public boolean isBigInteger(Object value) { - return value instanceof Integer || value instanceof BigInteger; - } - - @TypeCast - public BigInteger asBigInteger(Object value) { - if (value instanceof Integer) { - return BigInteger.valueOf((int) value); - } else { - return (BigInteger) value; - } + @ImplicitCast + public BigInteger castBigInteger(int integer) { + return BigInteger.valueOf(integer); } - @TypeCast - public BigInteger asBigInteger(int value) { - return BigInteger.valueOf(value); - } - - @TypeCheck - public boolean isBigInteger(@SuppressWarnings("unused") int value) { - return true; - } - - @ImplicitCast - public BigInteger castBigInteger(int value) { - return BigInteger.valueOf(value); - } }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BigIntegerLiteralNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BigIntegerLiteralNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -24,9 +24,10 @@ import java.math.*; -import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; -public abstract class BigIntegerLiteralNode extends TypedNode { +public final class BigIntegerLiteralNode extends TypedNode { private final BigInteger value; @@ -34,8 +35,14 @@ this.value = value; } - @Specialization - public BigInteger doBigInteger() { + @Override + public BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException { return value; } + + @Override + public Object executeGeneric(VirtualFrame frame) { + return value; + } + }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IntegerLiteralNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IntegerLiteralNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -22,9 +22,10 @@ */ package com.oracle.truffle.sl.nodes; -import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; -public abstract class IntegerLiteralNode extends TypedNode { +public final class IntegerLiteralNode extends TypedNode { private final int value; @@ -32,8 +33,13 @@ this.value = value; } - @Specialization - protected int doInteger() { - return this.value; + @Override + public int executeInteger(VirtualFrame frame) throws UnexpectedResultException { + return value; + } + + @Override + public Object executeGeneric(VirtualFrame frame) { + return value; } }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/StringLiteralNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/StringLiteralNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -22,9 +22,9 @@ */ package com.oracle.truffle.sl.nodes; -import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; -public abstract class StringLiteralNode extends TypedNode { +public final class StringLiteralNode extends TypedNode { private final String value; @@ -32,8 +32,14 @@ this.value = value; } - @Specialization - protected String doString() { + @Override + public String executeString(VirtualFrame frame) { return value; } + + @Override + public Object executeGeneric(VirtualFrame frame) { + return value; + } + }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java Mon Oct 14 11:24:04 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java Tue Oct 15 21:28:24 2013 +0200 @@ -36,14 +36,14 @@ this(node.slot); } - @Specialization(rewriteOn = FrameSlotTypeException.class) - public int write(VirtualFrame frame, int right) throws FrameSlotTypeException { + @Specialization + public int write(VirtualFrame frame, int right) { frame.setInt(slot, right); return right; } - @Specialization(rewriteOn = FrameSlotTypeException.class) - public boolean write(VirtualFrame frame, boolean right) throws FrameSlotTypeException { + @Specialization + public boolean write(VirtualFrame frame, boolean right) { frame.setBoolean(slot, right); return right; }
--- a/make/bsd/makefiles/fastdebug.make Mon Oct 14 11:24:04 2013 +0200 +++ b/make/bsd/makefiles/fastdebug.make Tue Oct 15 21:28:24 2013 +0200 @@ -59,6 +59,5 @@ MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug VERSION = fastdebug -#SYSDEFS += -DASSERT -DCHECK_UNHANDLED_OOPS -SYSDEFS += -DASSERT +SYSDEFS += -DASSERT -DCHECK_UNHANDLED_OOPS PICFLAGS = DEFAULT
--- a/make/linux/makefiles/fastdebug.make Mon Oct 14 11:24:04 2013 +0200 +++ b/make/linux/makefiles/fastdebug.make Tue Oct 15 21:28:24 2013 +0200 @@ -59,6 +59,5 @@ MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-debug VERSION = optimized -#SYSDEFS += -DASSERT -DCHECK_UNHANDLED_OOPS -SYSDEFS += -DASSERT +SYSDEFS += -DASSERT -DCHECK_UNHANDLED_OOPS PICFLAGS = DEFAULT
--- a/make/solaris/makefiles/fastdebug.make Mon Oct 14 11:24:04 2013 +0200 +++ b/make/solaris/makefiles/fastdebug.make Tue Oct 15 21:28:24 2013 +0200 @@ -126,6 +126,5 @@ MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE) VERSION = optimized -#SYSDEFS += -DASSERT -DCHECK_UNHANDLED_OOPS -SYSDEFS += -DASSERT +SYSDEFS += -DASSERT -DCHECK_UNHANDLED_OOPS PICFLAGS = DEFAULT
--- a/make/windows/makefiles/fastdebug.make Mon Oct 14 11:24:04 2013 +0200 +++ b/make/windows/makefiles/fastdebug.make Tue Oct 15 21:28:24 2013 +0200 @@ -38,8 +38,7 @@ !include ../local.make !include compile.make -#CXX_FLAGS=$(CXX_FLAGS) $(FASTDEBUG_OPT_OPTION) /D "CHECK_UNHANDLED_OOPS" -CXX_FLAGS=$(CXX_FLAGS) $(FASTDEBUG_OPT_OPTION) +CXX_FLAGS=$(CXX_FLAGS) $(FASTDEBUG_OPT_OPTION) /D "CHECK_UNHANDLED_OOPS" !include $(WorkSpace)/make/windows/makefiles/vm.make !include local.make
--- a/mx/commands.py Mon Oct 14 11:24:04 2013 +0200 +++ b/mx/commands.py Tue Oct 15 21:28:24 2013 +0200 @@ -955,12 +955,11 @@ vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) tasks.append(t.stop()) - # temporarily disable G1 verification until merge issues are resolved - # with VM('graal', 'product'): - # t = Task('BootstrapWithG1GCVerification:product') - # out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write - # vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+UseNewCode', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) - # tasks.append(t.stop()) + with VM('graal', 'product'): + t = Task('BootstrapWithG1GCVerification:product') + out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write + vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+UseNewCode', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) + tasks.append(t.stop()) with VM('graal', 'product'): t = Task('BootstrapWithRegisterPressure:product')
--- a/mx/projects Mon Oct 14 11:24:04 2013 +0200 +++ b/mx/projects Tue Oct 15 21:28:24 2013 +0200 @@ -28,7 +28,7 @@ library@OKRA@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.2.jar distribution@GRAAL@path=graal.jar -distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.hotspot.ptx,com.oracle.graal.truffle,com.oracle.graal.truffle.printer,com.oracle.graal.hotspot.sparc,com.oracle.graal.hotspot,com.oracle.graal.compiler.hsail +distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.hotspot.ptx,com.oracle.graal.truffle,com.oracle.graal.hotspot.sparc,com.oracle.graal.hotspot,com.oracle.graal.compiler.hsail # graal.api.runtime project@com.oracle.graal.api.runtime@subDir=graal @@ -613,7 +613,7 @@ # graal.truffle project@com.oracle.graal.truffle@subDir=graal project@com.oracle.graal.truffle@sourceDirs=src -project@com.oracle.graal.truffle@dependencies=com.oracle.truffle.api,com.oracle.graal.truffle.printer,com.oracle.graal.hotspot +project@com.oracle.graal.truffle@dependencies=com.oracle.truffle.api,com.oracle.graal.hotspot project@com.oracle.graal.truffle@checkstyle=com.oracle.graal.graph project@com.oracle.graal.truffle@javaCompliance=1.7 project@com.oracle.graal.truffle@workingSets=Graal,Truffle @@ -626,12 +626,4 @@ project@com.oracle.graal.truffle.test@javaCompliance=1.7 project@com.oracle.graal.truffle.test@workingSets=Graal,Truffle,Test -# graal.truffle.printer -project@com.oracle.graal.truffle.printer@subDir=graal -project@com.oracle.graal.truffle.printer@sourceDirs=src -project@com.oracle.graal.truffle.printer@dependencies=com.oracle.graal.nodes -project@com.oracle.graal.truffle.printer@checkstyle=com.oracle.graal.graph -project@com.oracle.graal.truffle.printer@javaCompliance=1.7 -project@com.oracle.graal.truffle.printer@workingSets=Graal,Truffle -
--- a/src/share/vm/code/nmethod.cpp Mon Oct 14 11:24:04 2013 +0200 +++ b/src/share/vm/code/nmethod.cpp Tue Oct 15 21:28:24 2013 +0200 @@ -1405,13 +1405,6 @@ // cache call. if (!is_osr_method() && !is_not_entrant()) { address stub = SharedRuntime::get_handle_wrong_method_stub(); -#ifdef GRAAL - if (_graal_installed_code != NULL) { - // Break the link between nmethod and HotSpotInstalledCode such that the nmethod can subsequently be flushed safely. - HotSpotInstalledCode::set_codeBlob(_graal_installed_code, 0); - _graal_installed_code = NULL; - } -#endif NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), stub); } @@ -1491,6 +1484,12 @@ } else { assert(state == not_entrant, "other cases may need to be handled differently"); } +#ifdef GRAAL + if (_graal_installed_code != NULL) { + // Break the link between nmethod and HotSpotInstalledCode such that the nmethod can subsequently be flushed safely. + HotSpotInstalledCode::set_codeBlob(_graal_installed_code, 0); + } +#endif if (TraceCreateZombies) { ResourceMark m;
--- a/src/share/vm/compiler/oopMap.cpp Mon Oct 14 11:24:04 2013 +0200 +++ b/src/share/vm/compiler/oopMap.cpp Tue Oct 15 21:28:24 2013 +0200 @@ -319,7 +319,7 @@ static void add_derived_oop(oop* base, oop* derived) { #ifndef TIERED COMPILER1_PRESENT(ShouldNotReachHere();) - GRAAL_ONLY(ShouldNotReachHere();) + GRAALVM_ONLY(ShouldNotReachHere();) #endif // TIERED #ifdef COMPILER2 DerivedPointerTable::add(derived, base); @@ -381,7 +381,7 @@ if (!oms.is_done()) { #ifndef TIERED COMPILER1_PRESENT(ShouldNotReachHere();) - GRAAL_ONLY(ShouldNotReachHere();) + GRAALVM_ONLY(ShouldNotReachHere();) #endif // !TIERED // Protect the operation on the derived pointers. This // protects the addition of derived pointers to the shared @@ -523,7 +523,7 @@ bool OopMap::has_derived_pointer() const { #ifndef TIERED COMPILER1_PRESENT(return false); - GRAAL_ONLY(return false); + GRAALVM_ONLY(return false); #endif // !TIERED #ifdef COMPILER2 OopMapStream oms((OopMap*)this,OopMapValue::derived_oop_value);
--- a/src/share/vm/graal/graalCompilerToVM.cpp Mon Oct 14 11:24:04 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Oct 15 21:28:24 2013 +0200 @@ -1132,6 +1132,7 @@ VM_Deoptimize op; VMThread::execute(&op); } + HotSpotInstalledCode::set_codeBlob(hotspotInstalledCode, 0); C2V_END
--- a/src/share/vm/graal/graalRuntime.cpp Mon Oct 14 11:24:04 2013 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Tue Oct 15 21:28:24 2013 +0200 @@ -108,7 +108,7 @@ thread->set_vm_result(obj); JRT_END -JRT_ENTRY(void, GraalRuntime::dynamic_new_array(JavaThread* thread, oop element_mirror, jint length)) +JRT_ENTRY(void, GraalRuntime::dynamic_new_array(JavaThread* thread, oopDesc* element_mirror, jint length)) oop obj = Reflection::reflect_new_array(element_mirror, length, CHECK); thread->set_vm_result(obj); JRT_END @@ -348,7 +348,7 @@ } JRT_END -JRT_ENTRY(void, GraalRuntime::log_object(JavaThread* thread, oop obj, jint flags)) +JRT_ENTRY(void, GraalRuntime::log_object(JavaThread* thread, oopDesc* obj, jint flags)) bool string = mask_bits_are_true(flags, LOG_OBJECT_STRING); bool addr = mask_bits_are_true(flags, LOG_OBJECT_ADDRESS); bool newline = mask_bits_are_true(flags, LOG_OBJECT_NEWLINE); @@ -393,7 +393,7 @@ return (jint)ret; JRT_END -JRT_ENTRY(void, GraalRuntime::vm_error(JavaThread* thread, oop where, oop format, jlong value)) +JRT_ENTRY(void, GraalRuntime::vm_error(JavaThread* thread, oopDesc* where, oopDesc* format, jlong value)) ResourceMark rm; assert(where == NULL || java_lang_String::is_instance(where), "must be"); const char *error_msg = where == NULL ? "<internal Graal error>" : java_lang_String::as_utf8_string(where); @@ -407,7 +407,7 @@ report_vm_error(__FILE__, __LINE__, error_msg, detail_msg); JRT_END -JRT_LEAF(oop, GraalRuntime::load_and_clear_exception(JavaThread* thread)) +JRT_LEAF(oopDesc*, GraalRuntime::load_and_clear_exception(JavaThread* thread)) oop exception = thread->exception_oop(); assert(exception != NULL, "npe"); thread->set_exception_oop(NULL); @@ -415,7 +415,7 @@ return exception; JRT_END -JRT_LEAF(void, GraalRuntime::log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3)) +JRT_LEAF(void, GraalRuntime::log_printf(JavaThread* thread, oopDesc* format, jlong v1, jlong v2, jlong v3)) ResourceMark rm; assert(format != NULL && java_lang_String::is_instance(format), "must be"); char *buf = java_lang_String::as_utf8_string(format); @@ -485,14 +485,14 @@ } JRT_END -JRT_ENTRY(jint, GraalRuntime::identity_hash_code(JavaThread* thread, oop obj)) +JRT_ENTRY(jint, GraalRuntime::identity_hash_code(JavaThread* thread, oopDesc* obj)) return (jint) obj->identity_hash(); JRT_END -JRT_ENTRY(jboolean, GraalRuntime::thread_is_interrupted(JavaThread* thread, oop receiver, jboolean clear_interrupted)) +JRT_ENTRY(jboolean, GraalRuntime::thread_is_interrupted(JavaThread* thread, oopDesc* receiver, jboolean clear_interrupted)) // Ensure that the C++ Thread and OSThread structures aren't freed before we operate Handle receiverHandle(thread, receiver); - MutexLockerEx ml(thread->threadObj() == receiver ? NULL : Threads_lock); + MutexLockerEx ml(thread->threadObj() == (void*)receiver ? NULL : Threads_lock); JavaThread* receiverThread = java_lang_Thread::thread(receiverHandle()); return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0); JRT_END
--- a/src/share/vm/graal/graalRuntime.hpp Mon Oct 14 11:24:04 2013 +0200 +++ b/src/share/vm/graal/graalRuntime.hpp Tue Oct 15 21:28:24 2013 +0200 @@ -33,18 +33,18 @@ static void new_instance(JavaThread* thread, Klass* klass); static void new_array(JavaThread* thread, Klass* klass, jint length); static void new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims); - static void dynamic_new_array(JavaThread* thread, oop element_mirror, jint length); - static jboolean thread_is_interrupted(JavaThread* thread, oop obj, jboolean clear_interrupted); + static void dynamic_new_array(JavaThread* thread, oopDesc* element_mirror, jint length); + static jboolean thread_is_interrupted(JavaThread* thread, oopDesc* obj, jboolean clear_interrupted); static void vm_message(jboolean vmError, jlong format, jlong v1, jlong v2, jlong v3); - static jint identity_hash_code(JavaThread* thread, oop obj); + static jint identity_hash_code(JavaThread* thread, oopDesc* obj); static address exception_handler_for_pc(JavaThread* thread); static void monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock); static void monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock); static void create_null_exception(JavaThread* thread); static void create_out_of_bounds_exception(JavaThread* thread, jint index); - static void vm_error(JavaThread* thread, oop where, oop format, jlong value); - static oop load_and_clear_exception(JavaThread* thread); - static void log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3); + static void vm_error(JavaThread* thread, oopDesc* where, oopDesc* format, jlong value); + static oopDesc* load_and_clear_exception(JavaThread* thread); + static void log_printf(JavaThread* thread, oopDesc* format, jlong v1, jlong v2, jlong v3); static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline); // Note: Must be kept in sync with constants in com.oracle.graal.replacements.Log enum { @@ -52,7 +52,7 @@ LOG_OBJECT_STRING = 0x02, LOG_OBJECT_ADDRESS = 0x04 }; - static void log_object(JavaThread* thread, oop msg, jint flags); + static void log_object(JavaThread* thread, oopDesc* msg, jint flags); static void write_barrier_pre(JavaThread* thread, oopDesc* obj); static void write_barrier_post(JavaThread* thread, void* card); static jboolean validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child);
--- a/src/share/vm/runtime/vframeArray.cpp Mon Oct 14 11:24:04 2013 +0200 +++ b/src/share/vm/runtime/vframeArray.cpp Tue Oct 15 21:28:24 2013 +0200 @@ -338,7 +338,7 @@ #ifndef PRODUCT if (PrintDeoptimizationDetails) { tty->print("Reconstructed expression %d (OBJECT): ", i); - oop o = (oop)(*addr); + oop o = (oop)(address)(*addr); if (o == NULL) { tty->print_cr("NULL"); } else { @@ -375,7 +375,7 @@ #ifndef PRODUCT if (PrintDeoptimizationDetails) { tty->print("Reconstructed local %d (OBJECT): ", i); - oop o = (oop)(*addr); + oop o = (oop)(address)(*addr); if (o == NULL) { tty->print_cr("NULL"); } else {