changeset 17030:2110fe2b7284

Merge
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Tue, 02 Sep 2014 19:23:43 -0700
parents 790e5e5072a2 (current diff) 66bf28082a14 (diff)
children 4f8c81b1d1cb
files graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterable.java
diffstat 51 files changed, 1408 insertions(+), 227 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Sep 02 19:23:43 2014 -0700
@@ -29,7 +29,6 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.graph.iterators.*;
 
 /**
@@ -278,7 +277,7 @@
     }
 
     public <T extends Node> T addOrUniqueWithInputs(T node) {
-        NodeClassIterator iterator = node.inputs().iterator();
+        NodePosIterator iterator = node.inputs().iterator();
         while (iterator.hasNext()) {
             Position pos = iterator.nextPosition();
             Node input = pos.get(node);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Sep 02 19:23:43 2014 -0700
@@ -28,7 +28,6 @@
 import java.util.*;
 
 import com.oracle.graal.graph.Graph.NodeEventListener;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodeinfo.*;
@@ -197,6 +196,9 @@
      * @return an {@link NodeClassIterable iterable} for all non-null input edges.
      */
     public NodeClassIterable inputs() {
+        if (USE_GENERATED_NODES) {
+            return inputsV2();
+        }
         return getNodeClass().getInputIterable(this);
     }
 
@@ -207,6 +209,9 @@
      * @return an {@link NodeClassIterable iterable} for all non-null successor edges.
      */
     public NodeClassIterable successors() {
+        if (USE_GENERATED_NODES) {
+            return successorsV2();
+        }
         return getNodeClass().getSuccessorIterable(this);
     }
 
@@ -610,7 +615,7 @@
     public void replaceAtUsages(InputType type, Node other) {
         assert checkReplaceWith(other);
         for (Node usage : usages().snapshot()) {
-            NodeClassIterator iter = usage.inputs().iterator();
+            NodePosIterator iter = usage.inputs().iterator();
             while (iter.hasNext()) {
                 Position pos = iter.nextPosition();
                 if (pos.getInputType(usage) == type && pos.get(usage) == this) {
@@ -822,7 +827,7 @@
             for (Node usage : usages()) {
                 assertFalse(usage.isDeleted(), "usage %s must never be deleted", usage);
                 assertTrue(usage.inputs().contains(this), "missing input in usage %s", usage);
-                NodeClassIterator iterator = usage.inputs().iterator();
+                NodePosIterator iterator = usage.inputs().iterator();
                 while (iterator.hasNext()) {
                     Position pos = iterator.nextPosition();
                     if (pos.get(usage) == this && pos.getInputType(usage) != InputType.Unchecked) {
@@ -832,7 +837,7 @@
                 }
             }
         }
-        NodeClassIterator iterator = inputs().withNullIterator();
+        NodePosIterator iterator = inputs().withNullIterator();
         while (iterator.hasNext()) {
             Position pos = iterator.nextPosition();
             assert pos.isInputOptional(this) || pos.get(this) != null : "non-optional input " + pos.getInputName(this) + " cannot be null in " + this + " (fix nullness or use @OptionalInput)";
@@ -980,7 +985,7 @@
                 formatter.format("}");
             }
 
-            NodeClassIterator inputIter = inputs().iterator();
+            NodePosIterator inputIter = inputs().iterator();
             while (inputIter.hasNext()) {
                 Position position = inputIter.nextPosition();
                 Node input = nodeClass.get(this, position);
@@ -1008,7 +1013,7 @@
                 formatter.format("}");
             }
 
-            NodeClassIterator succIter = successors().iterator();
+            NodePosIterator succIter = successors().iterator();
             while (succIter.hasNext()) {
                 Position position = succIter.nextPosition();
                 Node successor = nodeClass.get(this, position);
@@ -1025,8 +1030,12 @@
 
     // NEW API IMPLEMENTED BY GENERATED METHODS - NOT YET USED
 
-    public NodeRefIterable inputsV2() {
-        return NodeRefIterable.Empty;
+    public NodeClassIterable inputsV2() {
+        return NodeClassIterable.Empty;
+    }
+
+    public NodeClassIterable successorsV2() {
+        return NodeClassIterable.Empty;
     }
 
     public Collection<Position> getFirstLevelInputs() {
@@ -1038,6 +1047,57 @@
     }
 
     /**
+     * Gets an input or successor of this node at a given position.
+     *
+     * @param pos
+     */
+    public Node getNodeAt(Position pos) {
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * Gets an input or successor list at a given position.
+     *
+     * @param position
+     */
+    public NodeList<? extends Node> getNodeListAt(Position position) {
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * Sets an input or successor list at a given position.
+     *
+     * @param position
+     * @param list
+     */
+    public void setNodeListAt(Position position, NodeList<? extends Node> list) {
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * Updates an input or successor of this node at a given position. The existing, non-null input
+     * or successor at {@code position} is notified of the change via
+     * {@link #updateUsages(Node, Node)} or {@link #updatePredecessor(Node, Node)}.
+     *
+     * @param position
+     * @param value
+     */
+    public void updateNodeAt(Position position, Node value) {
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * Sets an input or successor of this node at a given position without notifying the existing
+     * input or successor at {@code position} of the change.
+     *
+     * @param position
+     * @param value
+     */
+    public void initializeNodeAt(Position position, Node value) {
+        throw new NoSuchElementException();
+    }
+
+    /**
      * @param pos
      */
     public InputType getInputTypeAt(Position pos) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Sep 02 19:23:43 2014 -0700
@@ -133,6 +133,39 @@
         this(clazz, new DefaultCalcOffset(), null, 0);
     }
 
+    /**
+     * Defines the order of fields in a node class that accessed via {@link Position}s.
+     */
+    public interface PositionFieldOrder {
+        /**
+         * Gets a field ordering specified by an ordered field name list. The only guarantee
+         * provided by this method is that all {@link NodeList} fields are preceded by all non
+         * {@link NodeList} fields.
+         *
+         * @param input specified whether input or successor field order is being requested
+         */
+        String[] getOrderedFieldNames(boolean input);
+    }
+
+    private static long[] sortedOffsets(boolean input, PositionFieldOrder pfo, Map<Long, String> names, ArrayList<Long> list1, ArrayList<Long> list2) {
+        if (list1.isEmpty() && list2.isEmpty()) {
+            return new long[0];
+        }
+        if (pfo != null) {
+            List<String> fields = Arrays.asList(pfo.getOrderedFieldNames(input));
+            long[] offsets = new long[fields.size()];
+            assert list1.size() + list2.size() == fields.size();
+            for (Map.Entry<Long, String> e : names.entrySet()) {
+                int index = fields.indexOf(e.getValue());
+                if (index != -1) {
+                    offsets[index] = e.getKey();
+                }
+            }
+            return offsets;
+        }
+        return sortedLongCopy(list1, list2);
+    }
+
     public NodeClass(Class<?> clazz, CalcOffset calcOffset, int[] presetIterableIds, int presetIterableId) {
         super(clazz);
         assert NODE_CLASS.isAssignableFrom(clazz);
@@ -148,7 +181,13 @@
         scanner.scan(clazz);
 
         directInputCount = scanner.inputOffsets.size();
-        inputOffsets = sortedLongCopy(scanner.inputOffsets, scanner.inputListOffsets);
+
+        isLeafNode = scanner.inputOffsets.isEmpty() && scanner.inputListOffsets.isEmpty() && scanner.successorOffsets.isEmpty() && scanner.successorListOffsets.isEmpty();
+
+        PositionFieldOrder pfo = lookupPositionFieldOrder(clazz);
+
+        inputOffsets = sortedOffsets(true, pfo, scanner.fieldNames, scanner.inputOffsets, scanner.inputListOffsets);
+
         inputTypes = new InputType[inputOffsets.length];
         inputOptional = new boolean[inputOffsets.length];
         for (int i = 0; i < inputOffsets.length; i++) {
@@ -157,7 +196,7 @@
             inputOptional[i] = scanner.optionalInputs.contains(inputOffsets[i]);
         }
         directSuccessorCount = scanner.successorOffsets.size();
-        successorOffsets = sortedLongCopy(scanner.successorOffsets, scanner.successorListOffsets);
+        successorOffsets = sortedOffsets(false, pfo, scanner.fieldNames, scanner.successorOffsets, scanner.successorListOffsets);
 
         dataOffsets = sortedLongCopy(scanner.dataOffsets);
         dataTypes = new Class[dataOffsets.length];
@@ -232,10 +271,21 @@
             this.iterableId = Node.NOT_ITERABLE;
             this.iterableIds = null;
         }
-        isLeafNode = (this.inputOffsets.length == 0 && this.successorOffsets.length == 0);
         nodeIterableCount = Debug.metric("NodeIterable_%s", shortName);
     }
 
+    private PositionFieldOrder lookupPositionFieldOrder(Class<?> clazz) throws GraalInternalError {
+        if (USE_GENERATED_NODES && !isAbstract(clazz.getModifiers()) && !isLeafNode) {
+            String name = clazz.getName().replace('$', '_') + "Gen$FieldOrder";
+            try {
+                return (PositionFieldOrder) Class.forName(name, true, getClazz().getClassLoader()).newInstance();
+            } catch (Exception e) {
+                throw new GraalInternalError("Could not find generated class " + name + " for " + getClazz());
+            }
+        }
+        return null;
+    }
+
     /**
      * Gets the {@linkplain GeneratedNode generated} node class (if any) described by the object.
      */
@@ -345,7 +395,6 @@
         public final ArrayList<Long> successorOffsets = new ArrayList<>();
         public final ArrayList<Long> successorListOffsets = new ArrayList<>();
         public final HashMap<Long, InputType> types = new HashMap<>();
-        public final HashMap<Long, String> names = new HashMap<>();
         public final HashSet<Long> optionalInputs = new HashSet<>();
 
         protected FieldScanner(CalcOffset calc) {
@@ -373,7 +422,6 @@
                 } else {
                     types.put(offset, field.getAnnotation(Node.OptionalInput.class).value());
                 }
-                names.put(offset, field.getName());
                 if (field.isAnnotationPresent(Node.OptionalInput.class)) {
                     optionalInputs.add(offset);
                 }
@@ -389,7 +437,6 @@
                     GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "Node successor field %s should not be final", field);
                     successorOffsets.add(offset);
                 }
-                names.put(offset, field.getName());
             } else {
                 GraalInternalError.guarantee(!NODE_CLASS.isAssignableFrom(type) || field.getName().equals("Null"), "suspicious node field: %s", field);
                 GraalInternalError.guarantee(!INPUT_LIST_CLASS.isAssignableFrom(type), "suspicious node input list field: %s", field);
@@ -445,7 +492,7 @@
      * An iterator of this type will not return null values, unless the field values are modified
      * concurrently. Concurrent modifications are detected by an assertion on a best-effort basis.
      */
-    public abstract static class NodeClassIterator implements Iterator<Node> {
+    public abstract static class NodeClassIterator implements NodePosIterator {
         protected final Node node;
         protected int index;
         protected int subIndex;
@@ -912,6 +959,9 @@
     }
 
     public Node get(Node node, Position pos) {
+        if (Node.USE_GENERATED_NODES) {
+            return node.getNodeAt(pos);
+        }
         long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()];
         if (pos.getSubIndex() == NOT_ITERABLE) {
             return getNode(node, offset);
@@ -931,6 +981,9 @@
     }
 
     public NodeList<?> getNodeList(Node node, Position pos) {
+        if (Node.USE_GENERATED_NODES) {
+            return node.getNodeListAt(pos);
+        }
         long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()];
         assert pos.getSubIndex() == Node.NODE_LIST;
         return getNodeList(node, offset);
@@ -1090,6 +1143,11 @@
     }
 
     public void set(Node node, Position pos, Node x) {
+        if (Node.USE_GENERATED_NODES) {
+            node.updateNodeAt(pos, x);
+            return;
+        }
+
         long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()];
         if (pos.getSubIndex() == NOT_ITERABLE) {
             Node old = getNode(node, offset);
@@ -1114,6 +1172,10 @@
     }
 
     public void initializePosition(Node node, Position pos, Node x) {
+        if (Node.USE_GENERATED_NODES) {
+            node.initializeNodeAt(pos, x);
+            return;
+        }
         long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()];
         if (pos.getSubIndex() == NOT_ITERABLE) {
             assert x == null || fieldTypes.get((pos.isInput() ? inputOffsets : successorOffsets)[pos.getIndex()]).isAssignableFrom(x.getClass()) : this + ".set(node, pos, " + x + ")";
@@ -1586,7 +1648,7 @@
 
     private static void transferValuesDifferentNodeClass(final Graph graph, final DuplicationReplacement replacements, final Map<Node, Node> newNodes, Node oldNode, Node node, NodeClass oldNodeClass,
                     NodeClass nodeClass) {
-        for (NodeClassIterator iter = oldNode.inputs().iterator(); iter.hasNext();) {
+        for (NodePosIterator iter = oldNode.inputs().iterator(); iter.hasNext();) {
             Position pos = iter.nextPosition();
             if (!nodeClass.isValid(pos, oldNodeClass)) {
                 continue;
@@ -1608,7 +1670,7 @@
             nodeClass.set(node, pos, target);
         }
 
-        for (NodeClassIterator iter = oldNode.successors().iterator(); iter.hasNext();) {
+        for (NodePosIterator iter = oldNode.successors().iterator(); iter.hasNext();) {
             Position pos = iter.nextPosition();
             if (!nodeClass.isValid(pos, oldNodeClass)) {
                 continue;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java	Tue Sep 02 19:23:43 2014 -0700
@@ -22,12 +22,11 @@
  */
 package com.oracle.graal.graph;
 
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.graph.iterators.*;
 
 /**
  * The iterator returned by this iterable can be used to access {@link Position Positions} during
- * iteration using {@link NodeClassIterator#nextPosition()}.
+ * iteration using {@link NodePosIterator#nextPosition()}.
  */
 public interface NodeClassIterable extends NodeIterable<Node> {
 
@@ -35,10 +34,21 @@
      * Returns an iterator that produces all non-null values.
      */
     @Override
-    NodeClassIterator iterator();
+    NodePosIterator iterator();
 
     /**
      * Returns an iterator that produces all values, including null values.
      */
-    NodeClassIterator withNullIterator();
+    NodePosIterator withNullIterator();
+
+    NodeClassIterable Empty = new NodeClassIterable() {
+
+        public NodeRefIterator withNullIterator() {
+            return NodeRefIterator.Empty;
+        }
+
+        public NodeRefIterator iterator() {
+            return NodeRefIterator.Empty;
+        }
+    };
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodePosIterator.java	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.graph;
+
+import java.util.*;
+
+/**
+ * Describes an edge slot for a {@link NodeClass}.
+ */
+public interface NodePosIterator extends Iterator<Node> {
+    Position nextPosition();
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterable.java	Tue Sep 02 19:01:01 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.graph;
-
-import com.oracle.graal.graph.iterators.*;
-
-/**
- * The iterator returned by this iterable can be used to access {@link Position Positions} during
- * iteration using {@link NodeRefIterator#nextPosition()}.
- */
-public interface NodeRefIterable extends NodeIterable<Node> {
-    /**
-     * Returns an iterator that produces all non-null values.
-     */
-    @Override
-    NodeRefIterator iterator();
-
-    /**
-     * Returns an iterator that produces all values, including null values.
-     */
-    NodeRefIterator withNullIterator();
-
-    NodeRefIterable Empty = new NodeRefIterable() {
-
-        public NodeRefIterator withNullIterator() {
-            return NodeRefIterator.Empty;
-        }
-
-        public NodeRefIterator iterator() {
-            return NodeRefIterator.Empty;
-        }
-    };
-}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterator.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterator.java	Tue Sep 02 19:23:43 2014 -0700
@@ -34,7 +34,7 @@
  * An iterator of this type will not return null values, unless the field values are modified
  * concurrently. Concurrent modifications are detected by an assertion on a best-effort basis.
  */
-public class NodeRefIterator implements Iterator<Node> {
+public class NodeRefIterator implements NodePosIterator {
 
     public static final NodeRefIterator Empty = new NodeRefIterator(0, 0, false);
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java	Tue Sep 02 19:23:43 2014 -0700
@@ -56,27 +56,47 @@
     }
 
     public Node get(Node node) {
+        if (Node.USE_GENERATED_NODES) {
+            return node.getNodeAt(this);
+        }
         return node.getNodeClass().get(node, this);
     }
 
     public InputType getInputType(Node node) {
+        if (Node.USE_GENERATED_NODES) {
+            return node.getInputTypeAt(this);
+        }
         return node.getNodeClass().getInputType(this);
     }
 
     public String getInputName(Node node) {
+        if (Node.USE_GENERATED_NODES) {
+            return node.getNameOf(this);
+        }
         return node.getNodeClass().getName(this);
     }
 
     public boolean isInputOptional(Node node) {
+        if (Node.USE_GENERATED_NODES) {
+            return node.isOptionalInputAt(this);
+        }
         return node.getNodeClass().isInputOptional(this);
     }
 
     public void set(Node node, Node value) {
-        node.getNodeClass().set(node, this, value);
+        if (Node.USE_GENERATED_NODES) {
+            node.updateNodeAt(this, value);
+        } else {
+            node.getNodeClass().set(node, this, value);
+        }
     }
 
     public void initialize(Node node, Node value) {
-        node.getNodeClass().initializePosition(node, this, value);
+        if (Node.USE_GENERATED_NODES) {
+            node.initializeNodeAt(this, value);
+        } else {
+            node.getNodeClass().initializePosition(node, this, value);
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Tue Sep 02 19:23:43 2014 -0700
@@ -29,7 +29,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -86,7 +85,7 @@
          * The code below assumes that all of the control split nodes have the same successor
          * structure, which should have been enforced by findUnswitchable.
          */
-        NodeClassIterator successors = firstNode.successors().iterator();
+        NodePosIterator successors = firstNode.successors().iterator();
         assert successors.hasNext();
         // original loop is used as first successor
         Position firstPosition = successors.nextPosition();
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Tue Sep 02 19:23:43 2014 -0700
@@ -28,7 +28,7 @@
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
@@ -84,7 +84,7 @@
         sb.append(loop).append(" at ");
         for (ControlSplitNode controlSplit : controlSplits) {
             sb.append(controlSplit).append(" [");
-            NodeClassIterator it = controlSplit.successors().iterator();
+            NodePosIterator it = controlSplit.successors().iterator();
             while (it.hasNext()) {
                 sb.append(controlSplit.probability((BeginNode) it.next()));
                 if (it.hasNext()) {
--- a/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeGenerator.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeGenerator.java	Tue Sep 02 19:23:43 2014 -0700
@@ -38,6 +38,8 @@
 
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.compiler.*;
+import com.oracle.truffle.dsl.processor.java.compiler.Compiler;
 import com.oracle.truffle.dsl.processor.java.model.*;
 
 /**
@@ -119,12 +121,16 @@
         return typeElement;
     }
 
+    public TypeElement getTypeElement(Class<?> cls) {
+        return getTypeElement(cls.getName());
+    }
+
     public TypeMirror getType(String name) {
         return getTypeElement(name).asType();
     }
 
-    public TypeMirror getType(Class<?> primitiveClass) {
-        return ElementUtils.getType(getProcessingEnv(), primitiveClass);
+    public TypeMirror getType(Class<?> cls) {
+        return ElementUtils.getType(getProcessingEnv(), cls);
     }
 
     public ProcessingEnvironment getProcessingEnv() {
@@ -158,9 +164,10 @@
     }
 
     private void scanFields(TypeElement node) {
+        Compiler compiler = CompilerFactory.getCompiler(node);
         TypeElement currentClazz = node;
         do {
-            for (VariableElement field : ElementFilter.fieldsIn(currentClazz.getEnclosedElements())) {
+            for (VariableElement field : ElementFilter.fieldsIn(compiler.getEnclosedElementsInDeclarationOrder(currentClazz))) {
                 Set<Modifier> modifiers = field.getModifiers();
                 if (modifiers.contains(STATIC) || modifiers.contains(TRANSIENT)) {
                     continue;
@@ -278,15 +285,15 @@
         Successors;
     }
 
-    CodeCompilationUnit process(TypeElement node) {
+    CodeCompilationUnit process(TypeElement node, boolean constructorsOnly) {
         try {
-            return process0(node);
+            return process0(node, constructorsOnly);
         } finally {
             reset();
         }
     }
 
-    private CodeCompilationUnit process0(TypeElement node) {
+    private CodeCompilationUnit process0(TypeElement node, boolean constructorsOnly) {
 
         CodeCompilationUnit compilationUnit = new CodeCompilationUnit();
 
@@ -308,55 +315,57 @@
             genClass.add(subConstructor);
         }
 
-        DeclaredType generatedNode = (DeclaredType) getType(GeneratedNode.class);
-        CodeAnnotationMirror generatedNodeMirror = new CodeAnnotationMirror(generatedNode);
-        generatedNodeMirror.setElementValue(generatedNodeMirror.findExecutableElement("value"), new CodeAnnotationValue(node.asType()));
-        genClass.getAnnotationMirrors().add(generatedNodeMirror);
+        if (!constructorsOnly) {
+            DeclaredType generatedNode = (DeclaredType) getType(GeneratedNode.class);
+            CodeAnnotationMirror generatedNodeMirror = new CodeAnnotationMirror(generatedNode);
+            generatedNodeMirror.setElementValue(generatedNodeMirror.findExecutableElement("value"), new CodeAnnotationValue(node.asType()));
+            genClass.getAnnotationMirrors().add(generatedNodeMirror);
+
+            scanFields(node);
 
-        scanFields(node);
+            boolean hasInputs = !inputFields.isEmpty() || !inputListFields.isEmpty();
+            boolean hasSuccessors = !successorFields.isEmpty() || !successorListFields.isEmpty();
 
-        boolean hasInputs = !inputFields.isEmpty() || !inputListFields.isEmpty();
-        boolean hasSuccessors = !successorFields.isEmpty() || !successorListFields.isEmpty();
+            if (hasInputs || hasSuccessors) {
+                createGetNodeAtMethod();
+                createGetInputTypeAtMethod();
+                createGetNameOfMethod();
+                createUpdateOrInitializeNodeAtMethod(false);
+                createUpdateOrInitializeNodeAtMethod(true);
+                createIsLeafNodeMethod();
+                createPositionAccessibleFieldOrderClass(packageElement);
 
-        if (hasInputs || hasSuccessors) {
-            createGetNodeAtMethod();
-            createGetInputTypeAtMethod();
-            createGetNameOfMethod();
-            createUpdateOrInitializeNodeAtMethod(false);
-            createUpdateOrInitializeNodeAtMethod(true);
-            createIsLeafNodeMethod(genClass);
+                if (!inputListFields.isEmpty() || !successorListFields.isEmpty()) {
+                    createGetNodeListAtMethod();
+                    createSetNodeListAtMethod();
+                }
+            }
+
+            if (hasInputs) {
+                createIsOptionalInputAtMethod();
+                createGetFirstLevelPositionsMethod(Inputs, inputFields, inputListFields);
+
+                createContainsMethod(Inputs, inputFields, inputListFields);
+                createIterableMethod(Inputs);
 
-            if (!inputListFields.isEmpty() || !successorListFields.isEmpty()) {
-                createGetNodeListAtMethod();
-                createSetNodeListAtMethod();
+                CodeTypeElement inputsIteratorClass = createIteratorClass(Inputs, packageElement, inputFields, inputListFields);
+                createAllIteratorClass(Inputs, inputsIteratorClass.asType(), packageElement, inputFields, inputListFields);
+                createWithModCountIteratorClass(Inputs, inputsIteratorClass.asType(), packageElement);
+                createIterableClass(Inputs, packageElement);
+            }
+
+            if (hasSuccessors) {
+                createGetFirstLevelPositionsMethod(Successors, successorFields, successorListFields);
+
+                createContainsMethod(Successors, successorFields, successorListFields);
+                createIterableMethod(Successors);
+
+                CodeTypeElement successorsIteratorClass = createIteratorClass(Successors, packageElement, successorFields, successorListFields);
+                createAllIteratorClass(Successors, successorsIteratorClass.asType(), packageElement, successorFields, successorListFields);
+                createWithModCountIteratorClass(Successors, successorsIteratorClass.asType(), packageElement);
+                createIterableClass(Successors, packageElement);
             }
         }
-
-        if (hasInputs) {
-            createIsOptionalInputAtMethod();
-            createGetFirstLevelPositionsMethod(Inputs, inputFields, inputListFields);
-
-            createContainsMethod(Inputs, inputFields, inputListFields);
-            createIterableMethod(Inputs);
-
-            CodeTypeElement inputsIteratorClass = createIteratorClass(Inputs, packageElement, inputFields, inputListFields);
-            createAllIteratorClass(Inputs, inputsIteratorClass.asType(), packageElement, inputFields, inputListFields);
-            createWithModCountIteratorClass(Inputs, inputsIteratorClass.asType(), packageElement);
-            createIterableClass(Inputs, packageElement);
-        }
-
-        if (hasSuccessors) {
-            createGetFirstLevelPositionsMethod(Successors, successorFields, successorListFields);
-
-            createContainsMethod(Successors, successorFields, successorListFields);
-            createIterableMethod(Successors);
-
-            CodeTypeElement successorsIteratorClass = createIteratorClass(Successors, packageElement, successorFields, successorListFields);
-            createAllIteratorClass(Successors, successorsIteratorClass.asType(), packageElement, successorFields, successorListFields);
-            createWithModCountIteratorClass(Successors, successorsIteratorClass.asType(), packageElement);
-            createIterableClass(Successors, packageElement);
-        }
-
         compilationUnit.add(genClass);
         return compilationUnit;
     }
@@ -430,10 +439,10 @@
         }
     }
 
-    private void createIsLeafNodeMethod(CodeTypeElement cls) {
+    private void createIsLeafNodeMethod() {
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isLeafNode");
         method.createBuilder().startReturn().string("false").end();
-        cls.add(method);
+        genClass.add(method);
         checkOnlyInGenNode(method);
     }
 
@@ -608,6 +617,29 @@
         b.end();
     }
 
+    private void createPositionAccessibleFieldOrderClass(PackageElement packageElement) {
+        CodeTypeElement cls = new CodeTypeElement(modifiers(PUBLIC, STATIC), ElementKind.CLASS, packageElement, "FieldOrder");
+        cls.getImplements().add(getType("com.oracle.graal.graph.NodeClass.PositionFieldOrder"));
+
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(String[].class), "getOrderedFieldNames");
+
+        method.addParameter(new CodeVariableElement(getType(boolean.class), "input"));
+
+        CodeTreeBuilder b = method.createBuilder();
+        b.startIf().string("input").end().startBlock();
+        String initializer = concat(inputFields, inputListFields).stream().map(v -> v.getSimpleName().toString()).collect(Collectors.joining("\", \"", "\"", "\""));
+        b.startStatement().string("return new String[] {", initializer, "}").end();
+        b.end();
+        b.startElseBlock();
+        initializer = concat(successorFields, successorListFields).stream().map(v -> v.getSimpleName().toString()).collect(Collectors.joining("\", \"", "\"", "\""));
+        b.startStatement().string("return new String[] {", initializer, "}").end();
+        b.end();
+        cls.add(method);
+
+        genClass.add(cls);
+
+    }
+
     private void createAllIteratorClass(NodeRefsType nodeRefsType, TypeMirror inputsIteratorType, PackageElement packageElement, List<VariableElement> nodeFields, List<VariableElement> nodeListFields) {
 
         String name = "All" + nodeRefsType + "Iterator";
@@ -696,7 +728,7 @@
 
         String name = nodeRefsType + "Iterable";
         CodeTypeElement cls = new CodeTypeElement(modifiers(PRIVATE), ElementKind.CLASS, packageElement, name);
-        cls.getImplements().add(getType("com.oracle.graal.graph.NodeRefIterable"));
+        cls.getImplements().add(getType("com.oracle.graal.graph.NodeClassIterable"));
 
         // iterator() method
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodeRefIterator"), "iterator");
@@ -710,7 +742,7 @@
         cls.add(method);
 
         // withNullIterator() method
-        method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodeRefIterator"), "withNullIterator");
+        method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodePosIterator"), "withNullIterator");
         b = method.createBuilder();
         b.startStatement().string("return new All" + nodeRefsType + "Iterator()").end();
         cls.add(method);
@@ -746,7 +778,7 @@
     private static final String API_TAG = "V2";
 
     private void createIterableMethod(NodeRefsType nodeRefsType) {
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodeRefIterable"), (nodeRefsType == Inputs ? "inputs" : "successors") +
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodeClassIterable"), (nodeRefsType == Inputs ? "inputs" : "successors") +
                         API_TAG);
         CodeTreeBuilder b = method.createBuilder();
         b.startStatement().string("return new " + nodeRefsType + "Iterable()").end();
@@ -783,7 +815,7 @@
     }
 
     private void createSetNodeListAtMethod() {
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(void.class), "SetNodeListAt");
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(void.class), "setNodeListAt");
 
         DeclaredType suppress = (DeclaredType) getType(SuppressWarnings.class);
         CodeAnnotationMirror suppressMirror = new CodeAnnotationMirror(suppress);
--- a/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeProcessor.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeProcessor.java	Tue Sep 02 19:23:43 2014 -0700
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodeinfo.processor;
 
 import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static java.util.Collections.*;
 
 import java.io.*;
 import java.util.*;
@@ -66,7 +67,9 @@
     void message(Kind kind, Element element, String format, Object... args) {
         if (scope != null && !isEnclosedIn(element, scope)) {
             // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=428357#c1
-            String loc = getElementHierarchy(element).stream().map(Object::toString).collect(Collectors.joining("."));
+            List<Element> elementHierarchy = getElementHierarchy(element);
+            reverse(elementHierarchy);
+            String loc = elementHierarchy.stream().filter(e -> e.getKind() != ElementKind.PACKAGE).map(Object::toString).collect(Collectors.joining("."));
             processingEnv.getMessager().printMessage(kind, String.format(loc + ": " + format, args), scope);
         } else {
             processingEnv.getMessager().printMessage(kind, String.format(format, args), element);
@@ -134,14 +137,16 @@
                 }
 
                 if (!typeElement.equals(gen.Node) && !typeElement.getModifiers().contains(Modifier.ABSTRACT)) {
-                    CodeCompilationUnit unit = gen.process(typeElement);
-                    unit.setGeneratorElement(typeElement);
-
-                    DeclaredType overrideType = (DeclaredType) ElementUtils.getType(processingEnv, Override.class);
-                    DeclaredType unusedType = (DeclaredType) ElementUtils.getType(processingEnv, SuppressWarnings.class);
-                    unit.accept(new GenerateOverrideVisitor(overrideType), null);
-                    unit.accept(new FixWarningsVisitor(processingEnv, unusedType, overrideType), null);
-                    unit.accept(new CodeWriter(processingEnv, typeElement), null);
+                    try {
+                        CodeCompilationUnit unit = gen.process(typeElement, false);
+                        emitCode(typeElement, unit);
+                    } catch (ElementException ee) {
+                        // Try to generate the class with just the constructors so that
+                        // spurious errors related to a missing class are not emitted
+                        CodeCompilationUnit unit = gen.process(typeElement, true);
+                        emitCode(typeElement, unit);
+                        throw ee;
+                    }
                 }
             } catch (ElementException ee) {
                 errorMessage(ee.element, ee.getMessage());
@@ -154,6 +159,16 @@
         return false;
     }
 
+    private void emitCode(TypeElement typeElement, CodeCompilationUnit unit) {
+        unit.setGeneratorElement(typeElement);
+
+        DeclaredType overrideType = (DeclaredType) ElementUtils.getType(processingEnv, Override.class);
+        DeclaredType unusedType = (DeclaredType) ElementUtils.getType(processingEnv, SuppressWarnings.class);
+        unit.accept(new GenerateOverrideVisitor(overrideType), null);
+        unit.accept(new FixWarningsVisitor(processingEnv, unusedType, overrideType), null);
+        unit.accept(new CodeWriter(processingEnv, typeElement), null);
+    }
+
     /**
      * Determines if a given exception is (most likely) caused by <a
      * href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599">Bug 367599</a>.
@@ -166,9 +181,9 @@
                     return true;
                 }
             }
-            if (t.getCause() != null) {
-                return isBug367599(t.getCause());
-            }
+        }
+        if (t.getCause() != null) {
+            return isBug367599(t.getCause());
         }
         return false;
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Tue Sep 02 19:23:43 2014 -0700
@@ -25,7 +25,7 @@
 import java.util.*;
 
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
@@ -127,7 +127,7 @@
     }
 
     private static BeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) {
-        NodeClassIterator successors = controlSplit.successors().iterator();
+        NodePosIterator successors = controlSplit.successors().iterator();
         BeginNode min = (BeginNode) successors.next();
         int minUsages = min.usages().count();
         while (successors.hasNext()) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Tue Sep 02 19:23:43 2014 -0700
@@ -33,7 +33,6 @@
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
@@ -497,7 +496,7 @@
             Node newOutsideClone = null;
             for (Node usage : unique) {
                 if (!duplicatedNodes.contains(usage)) {
-                    NodeClassIterator iter = usage.inputs().iterator();
+                    NodePosIterator iter = usage.inputs().iterator();
                     while (iter.hasNext()) {
                         Position pos = iter.nextPosition();
                         if (pos.get(usage) == duplicated) {
@@ -545,7 +544,7 @@
 
         private void processInputs(Node duplicated, HashSet<Node> duplicatedNodes, Deque<Node> worklist) {
             // check if this node has an input that lies outside and cannot be shared
-            NodeClassIterator iter = duplicated.inputs().iterator();
+            NodePosIterator iter = duplicated.inputs().iterator();
             while (iter.hasNext()) {
                 Position pos = iter.nextPosition();
                 Node input = pos.get(duplicated);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java	Tue Sep 02 19:23:43 2014 -0700
@@ -95,11 +95,11 @@
         } else {
             /*
              * Not comparable, two cases:
-             * 
+             *
              * Example 1: 'a' standing for j.l.Number and 'b' for j.l.String We return null for lack
              * of a value representing NullType, the right answer. Same goes when both arguments are
              * non-comparable interfaces.
-             * 
+             *
              * Example 2: 'a' standing for sun/nio/ch/DirectBuffer (an interface) and b for
              * java/nio/Buffer (an abstract class). The class always takes precedence.
              */
@@ -229,7 +229,7 @@
     @SuppressWarnings("unchecked")
     public static List<ValueNode> distinctValueAndConditionInputs(Node n) {
         ArrayList<ValueNode> result = null;
-        NodeClass.NodeClassIterator iter = n.inputs().iterator();
+        NodePosIterator iter = n.inputs().iterator();
         while (iter.hasNext()) {
             Position pos = iter.nextPosition();
             InputType inputType = pos.getInputType(n);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Tue Sep 02 19:23:43 2014 -0700
@@ -26,7 +26,7 @@
 
 import java.util.*;
 
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
 public final class ReentrantNodeIterator {
@@ -110,7 +110,7 @@
                 state = closure.processNode(current, state);
 
                 if (closure.continueIteration(state)) {
-                    NodeClassIterator successors = current.successors().iterator();
+                    NodePosIterator successors = current.successors().iterator();
                     if (!successors.hasNext()) {
                         if (current instanceof LoopEndNode) {
                             blockEndStates.put(current, state);
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Tue Sep 02 19:23:43 2014 -0700
@@ -34,7 +34,6 @@
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.java.*;
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
 import com.oracle.graal.lir.*;
@@ -367,7 +366,7 @@
         out.print(COLUMN_END).print(' ').println(COLUMN_END);
     }
 
-    private void printNamedNodes(Node node, NodeClassIterator iter, String prefix, String suffix, String hideSuffix) {
+    private void printNamedNodes(Node node, NodePosIterator iter, String prefix, String suffix, String hideSuffix) {
         int lastIndex = -1;
         while (iter.hasNext()) {
             Position pos = iter.nextPosition();
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Tue Sep 02 19:23:43 2014 -0700
@@ -30,7 +30,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
@@ -213,7 +212,7 @@
 
             // successors
             int fromIndex = 0;
-            NodeClassIterator succIter = node.successors().iterator();
+            NodePosIterator succIter = node.successors().iterator();
             while (succIter.hasNext()) {
                 Position position = succIter.nextPosition();
                 Node successor = node.getNodeClass().get(node, position);
@@ -225,7 +224,7 @@
 
             // inputs
             int toIndex = 1;
-            NodeClassIterator inputIter = node.inputs().iterator();
+            NodePosIterator inputIter = node.inputs().iterator();
             while (inputIter.hasNext()) {
                 Position position = inputIter.nextPosition();
                 Node input = node.getNodeClass().get(node, position);
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Tue Sep 02 19:23:43 2014 -0700
@@ -345,6 +345,17 @@
         return false;
     }
 
+    public void waitForCompilation(OptimizedCallTarget optimizedCallTarget, long timeout) throws ExecutionException, TimeoutException {
+        Future<?> codeTask = this.compilations.get(optimizedCallTarget);
+        if (codeTask != null && isCompiling(optimizedCallTarget)) {
+            try {
+                codeTask.get(timeout, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+                // ignore interrupted
+            }
+        }
+    }
+
     public boolean isCompiling(OptimizedCallTarget optimizedCallTarget) {
         Future<?> codeTask = this.compilations.get(optimizedCallTarget);
         if (codeTask != null) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/sl/TestCompilationThreshold.sl	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,19 @@
+/*
+ * This test verifies the compilation threshold property.
+ */
+function test() {
+}  
+
+function main() {  
+    /* TODO disableSplitting is required because otherwise it needs more calls to warm up. This still needs to be fixed. */
+    disableSplitting(test); 
+    threshold = getOption("TruffleCompilationThreshold");
+    i = 0;
+    while (i < threshold -1) {
+        test();
+        i = i + 1;
+    }
+    assertFalse(isOptimized(waitForOptimization(test)));
+    test();                         // triggers compilation
+    assertTrue(isOptimized(waitForOptimization(test)));
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/sl/TestInliningMaxCallerSize.sl	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,26 @@
+/* 
+ * This test verifies that CallTargets cannot exceed the TruffleInliningMaxCallerSize limit when inlining.
+ */
+function inlinableFunction() { 
+    generateDummyNodes(getOption("TruffleInliningMaxCallerSize") - 8);
+}
+
+function notInlinableFunction() { 
+    generateDummyNodes(getOption("TruffleInliningMaxCallerSize") - 7);
+}
+
+function test1() {
+    inlinableFunction(); 
+}
+
+function test2() {
+    notInlinableFunction(); 
+}
+
+function main() {
+    waitForOptimization(callUntilOptimized(test1));
+    assertTrue(isInlined(test1, inlinableFunction), "inlinableFunction is not inlined");
+    
+    waitForOptimization(callUntilOptimized(test2));
+    assertFalse(isInlined(test2, notInlinableFunction), "notInlinableFunction is inlined");
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SLTruffleGraalTestSuite.java	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test;
+
+import org.junit.*;
+import org.junit.runner.*;
+
+import com.oracle.graal.truffle.test.builtins.*;
+import com.oracle.truffle.sl.test.*;
+
+@RunWith(SLTestRunner.class)
+@SLTestSuite({"graal/com.oracle.graal.truffle.test/sl", "sl"})
+public class SLTruffleGraalTestSuite {
+
+    public static void main(String[] args) throws Exception {
+        SLTestRunner.runInMain(SLTruffleGraalTestSuite.class, args);
+    }
+
+    @BeforeClass
+    public static void setupTestRunner() {
+        SLTestRunner.setRepeats(1);
+        SLTestRunner.installBuiltin(SLGetOptionBuiltinFactory.getInstance());
+        SLTestRunner.installBuiltin(SLSetOptionBuiltinFactory.getInstance());
+        SLTestRunner.installBuiltin(SLIsOptimizedBuiltinFactory.getInstance());
+        SLTestRunner.installBuiltin(SLWaitForOptimizationBuiltinFactory.getInstance());
+        SLTestRunner.installBuiltin(SLDisableSplittingBuiltinFactory.getInstance());
+        SLTestRunner.installBuiltin(SLCallUntilOptimizedBuiltinFactory.getInstance());
+        SLTestRunner.installBuiltin(SLIsInlinedBuiltinFactory.getInstance());
+        SLTestRunner.installBuiltin(SLGenerateDummyNodesBuiltinFactory.getInstance());
+    }
+
+    /*
+     * Our "mx unittest" command looks for methods that are annotated with @Test. By just defining
+     * an empty method, this class gets included and the test suite is properly executed.
+     */
+    @Test
+    public void unittest() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLCallUntilOptimizedBuiltin.java	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.builtins;
+
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Calls a given function until the Graal runtime decides to optimize the function. Use
+ * <code>waitForOptimization(function)</code> to wait until the runtime system has completed the
+ * possibly parallel optimization.
+ *
+ * @see SLWaitForOptimizationBuiltin
+ */
+@NodeInfo(shortName = "callUntilOptimized")
+public abstract class SLCallUntilOptimizedBuiltin extends SLGraalRuntimeBuiltin {
+
+    private static final int MAX_CALLS = 10000;
+    private static final Object[] EMPTY_ARGS = new Object[0];
+
+    @Child private IndirectCallNode indirectCall = Truffle.getRuntime().createIndirectCallNode();
+
+    @Specialization
+    public SLFunction callUntilCompiled(VirtualFrame frame, SLFunction function) {
+        OptimizedCallTarget oct = ((OptimizedCallTarget) function.getCallTarget());
+        for (int i = 0; i < MAX_CALLS; i++) {
+            if (((GraalTruffleRuntime) Truffle.getRuntime()).isCompiling(oct) || oct.isValid()) {
+                break;
+            } else {
+                indirectCall.call(frame, oct, EMPTY_ARGS);
+            }
+        }
+        return function;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLDisableSplittingBuiltin.java	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.builtins;
+
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Disables splitting for a given {@link SLFunction} instance. If no function is given the splitting
+ * will be disabled for the calling function.
+ */
+@NodeInfo(shortName = "disableSplitting")
+public abstract class SLDisableSplittingBuiltin extends SLGraalRuntimeBuiltin {
+
+    @Specialization
+    @SlowPath
+    public SLFunction disableSplitting(SLFunction function) {
+        OptimizedCallTarget target = (OptimizedCallTarget) function.getCallTarget();
+        for (OptimizedCallTarget oct : findDuplicateCallTargets(target)) {
+            ((SLRootNode) oct.getRootNode()).setSplittable(false);
+        }
+        return function;
+    }
+
+    @Specialization
+    @SlowPath
+    public SLNull disableSplitting(@SuppressWarnings("unused") SLNull argument) {
+        RootNode parentRoot = Truffle.getRuntime().getCallerFrame().getCallNode().getRootNode();
+        ((SLRootNode) parentRoot).setSplittable(false);
+        return SLNull.SINGLETON;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLGenerateDummyNodesBuiltin.java	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.builtins;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Generates a given number of dummy nodes and replaces the root of the current method with them.
+ * This builtin is guaranteed to be executed only once.
+ */
+@NodeInfo(shortName = "generateDummyNodes")
+public abstract class SLGenerateDummyNodesBuiltin extends SLGraalRuntimeBuiltin {
+
+    @Specialization
+    public Object generateNodes(long count) {
+        CompilerAsserts.neverPartOfCompilation("generateNodes should never get optimized.");
+        FrameInstance callerFrame = Truffle.getRuntime().getCallerFrame();
+        SLRootNode root = (SLRootNode) callerFrame.getCallNode().getRootNode();
+        root.getBodyNode().replace(createBinaryTree((int) (count - 1)));
+        return SLNull.SINGLETON;
+    }
+
+    private SLDummyNode createBinaryTree(int nodeCount) {
+        if (nodeCount > 3) {
+            int leftSize = nodeCount / 2;
+            SLDummyNode left = createBinaryTree(leftSize);
+            SLDummyNode right = createBinaryTree(nodeCount - leftSize - 1);
+            return new SLDummyNode(left, right);
+        } else {
+            if (nodeCount <= 0) {
+                return null;
+            }
+            SLDummyNode left = null;
+            SLDummyNode right = null;
+            if (nodeCount > 1) {
+                left = new SLDummyNode(null, null);
+                if (nodeCount > 2) {
+                    right = new SLDummyNode(null, null);
+                }
+            }
+            return new SLDummyNode(left, right);
+        }
+    }
+
+    @NodeInfo(cost = NodeCost.MONOMORPHIC)
+    private static class SLDummyNode extends SLExpressionNode {
+
+        @Child private SLDummyNode left;
+        @Child private SLDummyNode right;
+
+        public SLDummyNode(SLDummyNode left, SLDummyNode right) {
+            super(null);
+            this.left = left;
+            this.right = right;
+        }
+
+        @Override
+        public Object executeGeneric(VirtualFrame frame) {
+            if (left != null) {
+                left.executeGeneric(frame);
+            }
+            if (right != null) {
+                right.executeGeneric(frame);
+            }
+            return null;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLGetOptionBuiltin.java	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.builtins;
+
+import com.oracle.graal.options.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.CompilerDirectives.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Looks up the value of an option in {@link TruffleCompilerOptions}. In the future this builtin
+ * might be extend to lookup other options as well.
+ */
+@NodeInfo(shortName = "getOption")
+public abstract class SLGetOptionBuiltin extends SLGraalRuntimeBuiltin {
+
+    @Specialization
+    @SlowPath
+    public Object getOption(String name) {
+        TruffleCompilerOptions_Options options = new TruffleCompilerOptions_Options();
+        for (OptionDescriptor option : options) {
+            if (option.getName().equals(name)) {
+                return convertValue(option.getOptionValue().getValue());
+            }
+        }
+        return null;
+    }
+
+    private static Object convertValue(Object value) {
+        // Improve this method as you need it.
+        if (value instanceof Integer) {
+            return (long) (int) value;
+        }
+        return value;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLGraalRuntimeBuiltin.java	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.builtins;
+
+import java.util.*;
+
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.builtins.*;
+
+public abstract class SLGraalRuntimeBuiltin extends SLBuiltinNode {
+
+    public SLGraalRuntimeBuiltin() {
+        super(null);
+        assignSourceSection(new NullSourceSection("SL Builtin", getClass().getAnnotation(NodeInfo.class).shortName()));
+        if (!(Truffle.getRuntime() instanceof GraalTruffleRuntime)) {
+            throw new AssertionError("Graal runtime builtins can only be used inside of a Graal runtime.");
+        }
+    }
+
+    /**
+     * Finds all call targets available for the same original call target. This might be useful if a
+     * {@link CallTarget} got duplicated due to splitting.
+     */
+    @SlowPath
+    protected static final Set<OptimizedCallTarget> findDuplicateCallTargets(OptimizedCallTarget originalCallTarget) {
+        final Set<OptimizedCallTarget> allCallTargets = new HashSet<>();
+        allCallTargets.add(originalCallTarget);
+        for (RootCallTarget target : Truffle.getRuntime().getCallTargets()) {
+            if (target instanceof OptimizedCallTarget) {
+                OptimizedCallTarget oct = (OptimizedCallTarget) target;
+                if (oct.getSplitSource() == originalCallTarget) {
+                    allCallTargets.add(oct);
+                }
+            }
+        }
+        return allCallTargets;
+    }
+
+    /**
+     * Finds all {@link DirectCallNode} instances calling a certain original {@link CallTarget} in
+     * the caller function.
+     */
+    @SlowPath
+    protected static final Set<DirectCallNode> findCallsTo(OptimizedCallTarget originalCallTarget) {
+        FrameInstance frame = Truffle.getRuntime().getCallerFrame();
+        RootNode root = frame.getCallNode().getRootNode();
+        return findCallsTo(root, originalCallTarget);
+    }
+
+    /**
+     * Finds all {@link DirectCallNode} instances calling a certain original {@link CallTarget} in a
+     * given {@link RootNode}.
+     */
+    @SlowPath
+    protected static final Set<DirectCallNode> findCallsTo(RootNode root, OptimizedCallTarget originalCallTarget) {
+        final Set<DirectCallNode> allCallNodes = new HashSet<>();
+        root.accept(new NodeVisitor() {
+            public boolean visit(Node node) {
+                if (node instanceof DirectCallNode) {
+                    DirectCallNode callNode = (DirectCallNode) node;
+                    if (callNode.getCallTarget() == originalCallTarget || callNode.getSplitCallTarget() == originalCallTarget) {
+                        allCallNodes.add(callNode);
+                    }
+                }
+                return true;
+            }
+        });
+        return allCallNodes;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLIsInlinedBuiltin.java	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.builtins;
+
+import java.util.*;
+
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.CompilerDirectives.SlowPath;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Returns <code>true</code> if a function got inlined for all calls from a given {@link SLFunction}
+ * . If no direct calls to the given {@link SLFunction} could be resolved or the call got inlined
+ * for some callsites and for some not then an {@link AssertionError} is thrown.
+ */
+@NodeInfo(shortName = "isInlined")
+public abstract class SLIsInlinedBuiltin extends SLGraalRuntimeBuiltin {
+
+    @Specialization
+    @SlowPath
+    public Object isInlined(SLFunction parent, SLFunction inlinedFunction) {
+        boolean allFalse = true;
+        boolean allTrue = true;
+        for (OptimizedCallTarget parentTarget : findDuplicateCallTargets((OptimizedCallTarget) parent.getCallTarget())) {
+            Set<DirectCallNode> callNodes = findCallsTo(parentTarget.getRootNode(), (OptimizedCallTarget) inlinedFunction.getCallTarget());
+            for (DirectCallNode directCall : callNodes) {
+                if (directCall.isInlined()) {
+                    allFalse = false;
+                } else {
+                    allTrue = false;
+                }
+            }
+        }
+        if (allFalse && allTrue) {
+            throw new AssertionError(String.format("No calls found from %s to %s .", parent, inlinedFunction));
+        } else if (!allFalse && !allTrue) {
+            throw new AssertionError(String.format("Some calls from %s to %s are inlined and some are not.", parent, inlinedFunction));
+        }
+        if (allTrue) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLIsOptimizedBuiltin.java	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.builtins;
+
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.CompilerDirectives.SlowPath;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Checks whether or not a function is optimized by the Graal runtime.
+ */
+@NodeInfo(shortName = "isOptimized")
+public abstract class SLIsOptimizedBuiltin extends SLGraalRuntimeBuiltin {
+
+    @Specialization
+    @SlowPath
+    public boolean isOptimized(SLFunction function) {
+        OptimizedCallTarget target = (OptimizedCallTarget) function.getCallTarget();
+        for (OptimizedCallTarget foundTarget : findDuplicateCallTargets(target)) {
+            if (foundTarget.isValid()) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLSetOptionBuiltin.java	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.builtins;
+
+import com.oracle.graal.options.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.CompilerDirectives.SlowPath;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Sets an option value in {@link TruffleCompilerOptions}. In the future this builtin might be
+ * extend to lookup other options as well.
+ */
+@NodeInfo(shortName = "setOption")
+public abstract class SLSetOptionBuiltin extends SLGraalRuntimeBuiltin {
+
+    @Specialization
+    @SlowPath
+    public Object setOption(String name, Object value) {
+        TruffleCompilerOptions_Options options = new TruffleCompilerOptions_Options();
+        for (OptionDescriptor option : options) {
+            if (option.getName().equals(name)) {
+                option.getOptionValue().setValue(convertValue(value));
+            }
+        }
+        return value;
+    }
+
+    private static Object convertValue(Object value) {
+        // Improve this method as you need it.
+        if (value instanceof Long) {
+            long longValue = (long) value;
+            if (longValue == (int) longValue) {
+                return (int) longValue;
+            }
+        }
+        return value;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLWaitForOptimizationBuiltin.java	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.builtins;
+
+import java.util.concurrent.*;
+
+import com.oracle.graal.truffle.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Waits for the optimization of a function to complete if it was already triggered. If no
+ * optimization was triggered then this builtin does nothing.
+ */
+@NodeInfo(shortName = "waitForOptimization")
+public abstract class SLWaitForOptimizationBuiltin extends SLGraalRuntimeBuiltin {
+
+    @Specialization
+    public SLFunction waitForOptimization(SLFunction function, long timeout) {
+        OptimizedCallTarget target = (OptimizedCallTarget) function.getCallTarget();
+        GraalTruffleRuntime runtime = ((GraalTruffleRuntime) Truffle.getRuntime());
+
+        for (OptimizedCallTarget effectiveCallTarget : findDuplicateCallTargets(target)) {
+            try {
+                runtime.waitForCompilation(effectiveCallTarget, timeout);
+            } catch (ExecutionException | TimeoutException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return function;
+    }
+
+    @Specialization
+    public SLFunction waitForCompilation(SLFunction function, @SuppressWarnings("unused") SLNull timeout) {
+        return waitForOptimization(function, 120000);
+    }
+
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Tue Sep 02 19:23:43 2014 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.truffle;
 
+import java.util.concurrent.*;
+
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.truffle.api.*;
 
@@ -33,6 +35,8 @@
 
     boolean cancelInstalledTask(OptimizedCallTarget optimizedCallTarget);
 
+    void waitForCompilation(OptimizedCallTarget optimizedCallTarget, long timeout) throws ExecutionException, TimeoutException;
+
     boolean isCompiling(OptimizedCallTarget optimizedCallTarget);
 
     void invalidateInstalledCode(OptimizedCallTarget optimizedCallTarget);
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Tue Sep 02 19:23:43 2014 -0700
@@ -81,41 +81,39 @@
                     state.addCacheEntry(identifier, value);
                 }
             }
-        } else if (node instanceof FixedAccessNode) {
-            if (node instanceof ReadNode) {
-                ReadNode read = (ReadNode) node;
-                if (read.location() instanceof ConstantLocationNode) {
-                    ValueNode object = GraphUtil.unproxify(read.object());
-                    ReadCacheEntry identifier = new ReadCacheEntry(object, read.location());
-                    ValueNode cachedValue = state.getCacheEntry(identifier);
-                    if (cachedValue != null) {
-                        if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) {
-                            effects.addFixedNodeBefore(ValueAnchorNode.create((ValueNode) read.getGuard()), read);
-                        }
-                        effects.replaceAtUsages(read, cachedValue);
-                        addScalarAlias(read, cachedValue);
-                        deleted = true;
-                    } else {
-                        state.addCacheEntry(identifier, read);
+        } else if (node instanceof ReadNode) {
+            ReadNode read = (ReadNode) node;
+            if (read.location() instanceof ConstantLocationNode) {
+                ValueNode object = GraphUtil.unproxify(read.object());
+                ReadCacheEntry identifier = new ReadCacheEntry(object, read.location());
+                ValueNode cachedValue = state.getCacheEntry(identifier);
+                if (cachedValue != null) {
+                    if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) {
+                        effects.addFixedNodeBefore(ValueAnchorNode.create((ValueNode) read.getGuard()), read);
                     }
+                    effects.replaceAtUsages(read, cachedValue);
+                    addScalarAlias(read, cachedValue);
+                    deleted = true;
+                } else {
+                    state.addCacheEntry(identifier, read);
                 }
-            } else if (node instanceof WriteNode) {
-                WriteNode write = (WriteNode) node;
-                if (write.location() instanceof ConstantLocationNode) {
-                    ValueNode object = GraphUtil.unproxify(write.object());
-                    ReadCacheEntry identifier = new ReadCacheEntry(object, write.location());
-                    ValueNode cachedValue = state.getCacheEntry(identifier);
+            }
+        } else if (node instanceof WriteNode) {
+            WriteNode write = (WriteNode) node;
+            if (write.location() instanceof ConstantLocationNode) {
+                ValueNode object = GraphUtil.unproxify(write.object());
+                ReadCacheEntry identifier = new ReadCacheEntry(object, write.location());
+                ValueNode cachedValue = state.getCacheEntry(identifier);
 
-                    ValueNode value = getScalarAlias(write.value());
-                    if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
-                        effects.deleteFixedNode(write);
-                        deleted = true;
-                    }
-                    processIdentity(state, write.location().getLocationIdentity());
-                    state.addCacheEntry(identifier, value);
-                } else {
-                    processIdentity(state, write.location().getLocationIdentity());
+                ValueNode value = getScalarAlias(write.value());
+                if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
+                    effects.deleteFixedNode(write);
+                    deleted = true;
                 }
+                processIdentity(state, write.location().getLocationIdentity());
+                state.addCacheEntry(identifier, value);
+            } else {
+                processIdentity(state, write.location().getLocationIdentity());
             }
         } else if (node instanceof UnsafeAccessNode) {
             if (node instanceof UnsafeLoadNode) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Tue Sep 02 19:23:43 2014 -0700
@@ -41,6 +41,9 @@
 public class ElementUtils {
 
     public static TypeMirror getType(ProcessingEnvironment processingEnv, Class<?> element) {
+        if (element.isArray()) {
+            return processingEnv.getTypeUtils().getArrayType(getType(processingEnv, element.getComponentType()));
+        }
         if (element.isPrimitive()) {
             if (element == void.class) {
                 return processingEnv.getTypeUtils().getNoType(TypeKind.VOID);
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java	Tue Sep 02 19:23:43 2014 -0700
@@ -36,14 +36,16 @@
 import org.junit.runners.*;
 import org.junit.runners.model.*;
 
+import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.builtins.*;
 import com.oracle.truffle.sl.runtime.*;
 import com.oracle.truffle.sl.test.SLTestRunner.TestCase;
 
 public final class SLTestRunner extends ParentRunner<TestCase> {
 
-    private static final int REPEATS = 10;
+    private static int repeats = 1;
 
     private static final String SOURCE_SUFFIX = ".sl";
     private static final String INPUT_SUFFIX = ".input";
@@ -147,6 +149,16 @@
         return outFile.toString();
     }
 
+    public static void setRepeats(int repeats) {
+        SLTestRunner.repeats = repeats;
+    }
+
+    private static final List<NodeFactory<? extends SLBuiltinNode>> builtins = new ArrayList<>();
+
+    public static void installBuiltin(NodeFactory<? extends SLBuiltinNode> builtin) {
+        builtins.add(builtin);
+    }
+
     @Override
     protected void runChild(TestCase testCase, RunNotifier notifier) {
         notifier.fireTestStarted(testCase.name);
@@ -154,12 +166,15 @@
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         PrintStream printer = new PrintStream(out);
         try {
-            SLContext context = new SLContext(new BufferedReader(new StringReader(repeat(testCase.testInput, REPEATS))), printer);
+            SLContext context = new SLContext(new BufferedReader(new StringReader(repeat(testCase.testInput, repeats))), printer);
+            for (NodeFactory<? extends SLBuiltinNode> builtin : builtins) {
+                context.installBuiltin(builtin);
+            }
             final Source source = Source.fromText(readAllLines(testCase.path), testCase.sourceName);
-            SLMain.run(context, source, null, REPEATS);
+            SLMain.run(context, source, null, repeats);
 
             String actualOutput = new String(out.toByteArray());
-            Assert.assertEquals(repeat(testCase.expectedOutput, REPEATS), actualOutput);
+            Assert.assertEquals(repeat(testCase.expectedOutput, repeats), actualOutput);
         } catch (Throwable ex) {
             notifier.fireTestFailure(new Failure(testCase.name, ex));
         } finally {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLAssertionError.java	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl;
+
+/**
+ * An implementation of an {@link AssertionError} also containing the guest language stack trace.
+ */
+public class SLAssertionError extends AssertionError {
+
+    private static final long serialVersionUID = -9138475336963945873L;
+
+    public SLAssertionError(String message) {
+        super(message);
+        initCause(new AssertionError("Java stack trace"));
+    }
+
+    @Override
+    public synchronized Throwable fillInStackTrace() {
+        return SLException.fillInSLStackTrace(this);
+    }
+
+}
\ No newline at end of file
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLException.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLException.java	Tue Sep 02 19:23:43 2014 -0700
@@ -22,15 +22,74 @@
  */
 package com.oracle.truffle.sl;
 
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
 /**
  * SL does not need a sophisticated error checking and reporting mechanism, so all unexpected
  * conditions just abort execution. This exception class is used when we abort from within the SL
  * implementation.
  */
 public class SLException extends RuntimeException {
+
     private static final long serialVersionUID = -6799734410727348507L;
 
     public SLException(String message) {
         super(message);
+        initCause(new Throwable("Java stack trace"));
+    }
+
+    @Override
+    public synchronized Throwable fillInStackTrace() {
+        return fillInSLStackTrace(this);
+    }
+
+    /**
+     * Uses the Truffle API to iterate the stack frames and to create and set Java
+     * {@link StackTraceElement} elements based on the source sections of the call nodes on the
+     * stack.
+     */
+    static Throwable fillInSLStackTrace(Throwable t) {
+        final List<StackTraceElement> stackTrace = new ArrayList<>();
+        Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Void>() {
+            public Void visitFrame(FrameInstance frame) {
+                Node callNode = frame.getCallNode();
+                if (callNode == null) {
+                    return null;
+                }
+                RootNode root = callNode.getRootNode();
+
+                /*
+                 * There should be no RootNodes other than SLRootNodes on the stack. Just for the
+                 * case if this would change.
+                 */
+                String methodName = "$unknownFunction";
+                if (root instanceof SLRootNode) {
+                    methodName = ((SLRootNode) root).getName();
+                }
+
+                SourceSection sourceSection = callNode.getEncapsulatingSourceSection();
+                Source source = sourceSection != null ? sourceSection.getSource() : null;
+                String sourceName = source != null ? source.getName() : null;
+                int lineNumber;
+                try {
+                    lineNumber = sourceSection != null ? sourceSection.getLineLocation().getLineNumber() : -1;
+                } catch (UnsupportedOperationException e) {
+                    /*
+                     * SourceSection#getLineLocation() may throw an UnsupportedOperationException.
+                     */
+                    lineNumber = -1;
+                }
+                stackTrace.add(new StackTraceElement("SL", methodName, sourceName, lineNumber));
+                return null;
+            }
+        });
+        t.setStackTrace(stackTrace.toArray(new StackTraceElement[stackTrace.size()]));
+        return t;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertFalseBuiltin.java	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Asserts a given value to be <code>false</code> and throws an {@link AssertionError} if the value
+ * was <code>true</code>.
+ */
+@NodeInfo(shortName = "assertFalse")
+public abstract class SLAssertFalseBuiltin extends SLBuiltinNode {
+
+    public SLAssertFalseBuiltin() {
+        super(new NullSourceSection("SL builtin", "assertFalse"));
+    }
+
+    @Specialization
+    public boolean doAssert(boolean value, String message) {
+        if (value) {
+            CompilerDirectives.transferToInterpreter();
+            throw new SLAssertionError(message == null ? "" : message);
+        }
+        return value;
+    }
+
+    @Specialization
+    public boolean doAssertNull(boolean value, @SuppressWarnings("unused") SLNull message) {
+        return doAssert(value, null);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertTrueBuiltin.java	Tue Sep 02 19:23:43 2014 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Asserts a given value to be <code>true</code> and throws an {@link AssertionError} if the value
+ * was <code>false</code>.
+ */
+@NodeInfo(shortName = "assertTrue")
+public abstract class SLAssertTrueBuiltin extends SLBuiltinNode {
+
+    public SLAssertTrueBuiltin() {
+        super(new NullSourceSection("SL builtin", "assertTrue"));
+    }
+
+    @Specialization
+    public boolean doAssert(boolean value, String message) {
+        if (!value) {
+            CompilerDirectives.transferToInterpreter();
+            throw new SLAssertionError(message == null ? "" : message);
+        }
+        return value;
+    }
+
+    @Specialization
+    public boolean doAssertNull(boolean value, @SuppressWarnings("unused") SLNull message) {
+        return doAssert(value, null);
+    }
+
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java	Tue Sep 02 19:23:43 2014 -0700
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.sl.nodes;
 
+import com.oracle.truffle.api.CompilerDirectives.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.builtins.*;
@@ -53,6 +54,8 @@
     /** The Simple execution context for this tree **/
     private final SLContext context;
 
+    @CompilationFinal private boolean isSplittable;
+
     public SLRootNode(SLContext context, FrameDescriptor frameDescriptor, SLExpressionNode bodyNode, String name) {
         super(null, frameDescriptor);
         /* Deep copy the body before any specialization occurs during execution. */
@@ -67,9 +70,21 @@
         return bodyNode.executeGeneric(frame);
     }
 
+    public String getName() {
+        return name;
+    }
+
+    public void setSplittable(boolean isSplittable) {
+        this.isSplittable = isSplittable;
+    }
+
+    public SLExpressionNode getBodyNode() {
+        return bodyNode;
+    }
+
     @Override
     public boolean isSplittable() {
-        return true;
+        return isSplittable;
     }
 
     @Override
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Tue Sep 02 19:01:01 2014 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Tue Sep 02 19:23:43 2014 -0700
@@ -109,9 +109,11 @@
         installBuiltin(SLDefineFunctionBuiltinFactory.getInstance());
         installBuiltin(SLStackTraceBuiltinFactory.getInstance());
         installBuiltin(SLHelloEqualsWorldBuiltinFactory.getInstance());
+        installBuiltin(SLAssertTrueBuiltinFactory.getInstance());
+        installBuiltin(SLAssertFalseBuiltinFactory.getInstance());
     }
 
-    private void installBuiltin(NodeFactory<? extends SLBuiltinNode> factory) {
+    public void installBuiltin(NodeFactory<? extends SLBuiltinNode> factory) {
         /*
          * The builtin node factory is a class that is automatically generated by the Truffle DSL.
          * The signature returned by the factory reflects the signature of the @Specialization
--- a/make/bsd/makefiles/mapfile-vers-debug	Tue Sep 02 19:01:01 2014 -0700
+++ b/make/bsd/makefiles/mapfile-vers-debug	Tue Sep 02 19:23:43 2014 -0700
@@ -161,6 +161,7 @@
                 _JVM_GetStackTraceElement
                 _JVM_GetSystemPackage
                 _JVM_GetSystemPackages
+                _JVM_GetTemporaryDirectory
                 _JVM_GetThreadStateNames
                 _JVM_GetThreadStateValues
                 _JVM_GetVersionInfo
--- a/make/bsd/makefiles/mapfile-vers-product	Tue Sep 02 19:01:01 2014 -0700
+++ b/make/bsd/makefiles/mapfile-vers-product	Tue Sep 02 19:23:43 2014 -0700
@@ -161,6 +161,7 @@
                 _JVM_GetStackTraceElement
                 _JVM_GetSystemPackage
                 _JVM_GetSystemPackages
+                _JVM_GetTemporaryDirectory
                 _JVM_GetThreadStateNames
                 _JVM_GetThreadStateValues
                 _JVM_GetVersionInfo
--- a/make/linux/makefiles/mapfile-vers-debug	Tue Sep 02 19:01:01 2014 -0700
+++ b/make/linux/makefiles/mapfile-vers-debug	Tue Sep 02 19:23:43 2014 -0700
@@ -122,7 +122,7 @@
                 JVM_GetClassModifiers;
                 JVM_GetClassName;
                 JVM_GetClassNameUTF;
-		JVM_GetClassSignature;
+                JVM_GetClassSignature;
                 JVM_GetClassSigners;
                 JVM_GetClassTypeAnnotations;
                 JVM_GetComponentType;
@@ -163,6 +163,7 @@
                 JVM_GetStackTraceElement;
                 JVM_GetSystemPackage;
                 JVM_GetSystemPackages;
+                JVM_GetTemporaryDirectory;
                 JVM_GetThreadStateNames;
                 JVM_GetThreadStateValues;
                 JVM_GetVersionInfo;
--- a/make/linux/makefiles/mapfile-vers-product	Tue Sep 02 19:01:01 2014 -0700
+++ b/make/linux/makefiles/mapfile-vers-product	Tue Sep 02 19:23:43 2014 -0700
@@ -163,6 +163,7 @@
                 JVM_GetStackTraceElement;
                 JVM_GetSystemPackage;
                 JVM_GetSystemPackages;
+                JVM_GetTemporaryDirectory;
                 JVM_GetThreadStateNames;
                 JVM_GetThreadStateValues;
                 JVM_GetVersionInfo;
--- a/make/solaris/makefiles/mapfile-vers	Tue Sep 02 19:01:01 2014 -0700
+++ b/make/solaris/makefiles/mapfile-vers	Tue Sep 02 19:23:43 2014 -0700
@@ -163,6 +163,7 @@
                 JVM_GetStackTraceElement;
                 JVM_GetSystemPackage;
                 JVM_GetSystemPackages;
+                JVM_GetTemporaryDirectory;
                 JVM_GetThreadStateNames;
                 JVM_GetThreadStateValues;
                 JVM_GetVersionInfo;
--- a/mx/mx_graal.py	Tue Sep 02 19:01:01 2014 -0700
+++ b/mx/mx_graal.py	Tue Sep 02 19:23:43 2014 -0700
@@ -199,7 +199,7 @@
 
     infos['jdkversion'] = str(mx.java().version)
 
-    infos['architecture'] = _arch()
+    infos['architecture'] = mx.get_arch()
     infos['platform'] = mx.get_os()
 
     if mx.get_os != 'windows':
@@ -346,22 +346,6 @@
 
     _run_benchmark(args, sanitycheck.dacapoScalaSanityWarmup.keys(), launcher)
 
-def _arch():
-    machine = platform.uname()[4]
-    if machine in ['amd64', 'AMD64', 'x86_64', 'i86pc']:
-        return 'amd64'
-    if machine in ['sun4v', 'sun4u']:
-        return 'sparcv9'
-    if machine == 'i386' and mx.get_os() == 'darwin':
-        try:
-            # Support for Snow Leopard and earlier version of MacOSX
-            if subprocess.check_output(['sysctl', '-n', 'hw.cpu64bit_capable']).strip() == '1':
-                return 'amd64'
-        except OSError:
-            # sysctl is not available
-            pass
-    mx.abort('unknown or unsupported architecture: os=' + mx.get_os() + ', machine=' + machine)
-
 def _vmLibDirInJdk(jdk):
     """
     Get the directory within a JDK where the server and client
@@ -371,15 +355,25 @@
         return join(jdk, 'jre', 'lib')
     if platform.system() == 'Windows':
         return join(jdk, 'jre', 'bin')
-    return join(jdk, 'jre', 'lib', _arch())
+    return join(jdk, 'jre', 'lib', mx.get_arch())
 
-def _vmCfgInJdk(jdk):
+def _vmJliLibDirs(jdk):
+    """
+    Get the directories within a JDK where the jli library designates to.
+    """
+    if platform.system() == 'Darwin':
+        return [join(jdk, 'jre', 'lib', 'jli')]
+    if platform.system() == 'Windows':
+        return [join(jdk, 'jre', 'bin'), join(jdk, 'bin')]
+    return [join(jdk, 'jre', 'lib', mx.get_arch(), 'jli'), join(jdk, 'lib', mx.get_arch(), 'jli')]
+
+def _vmCfgInJdk(jdk, jvmCfgFile='jvm.cfg'):
     """
     Get the jvm.cfg file.
     """
     if platform.system() == 'Windows':
-        return join(jdk, 'jre', 'lib', _arch(), 'jvm.cfg')
-    return join(_vmLibDirInJdk(jdk), 'jvm.cfg')
+        return join(jdk, 'jre', 'lib', mx.get_arch(), jvmCfgFile)
+    return join(_vmLibDirInJdk(jdk), jvmCfgFile)
 
 def _jdksDir():
     return os.path.abspath(join(_installed_jdks if _installed_jdks else _graal_home, 'jdk' + str(mx.java().version)))
@@ -1952,7 +1946,7 @@
     flavor = 'intel'
     if 'att' in args:
         flavor = 'att'
-    lib = mx.add_lib_suffix('hsdis-' + _arch())
+    lib = mx.add_lib_suffix('hsdis-' + mx.get_arch())
     path = join(_graal_home, 'lib', lib)
 
     sha1s = {
--- a/mx/projects	Tue Sep 02 19:01:01 2014 -0700
+++ b/mx/projects	Tue Sep 02 19:23:43 2014 -0700
@@ -843,7 +843,7 @@
 # graal.truffle.test
 project@com.oracle.graal.truffle.test@subDir=graal
 project@com.oracle.graal.truffle.test@sourceDirs=src
-project@com.oracle.graal.truffle.test@dependencies=com.oracle.graal.truffle,com.oracle.graal.compiler.test
+project@com.oracle.graal.truffle.test@dependencies=com.oracle.graal.truffle,com.oracle.graal.compiler.test,com.oracle.truffle.sl.test
 project@com.oracle.graal.truffle.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.truffle.test@javaCompliance=1.8
 project@com.oracle.graal.truffle.test@workingSets=Graal,Truffle,Test
--- a/mxtool/mx.py	Tue Sep 02 19:01:01 2014 -0700
+++ b/mxtool/mx.py	Tue Sep 02 19:23:43 2014 -0700
@@ -33,7 +33,7 @@
 Full documentation can be found at https://wiki.openjdk.java.net/display/Graal/The+mx+Tool
 """
 
-import sys, os, errno, time, subprocess, shlex, types, StringIO, zipfile, signal, xml.sax.saxutils, tempfile, fnmatch
+import sys, os, errno, time, subprocess, shlex, types, StringIO, zipfile, signal, xml.sax.saxutils, tempfile, fnmatch, platform
 import multiprocessing
 import textwrap
 import socket
@@ -905,6 +905,11 @@
             self.jreLibs.append(l)
 
         for name, attrs in libsMap.iteritems():
+            if "|" in name:
+                assert name.count("|") == 2, "syntax: libname|os-platform|architecture"
+                name, platform, architecture = name.split("|")
+                if platform != get_os() or architecture != get_arch():
+                    continue
             path = attrs.pop('path')
             urls = pop_list(attrs, 'urls')
             sha1 = attrs.pop('sha1', None)
@@ -1207,6 +1212,22 @@
     else:
         abort('Unknown operating system ' + sys.platform)
 
+def get_arch():
+    machine = platform.uname()[4]
+    if machine in ['amd64', 'AMD64', 'x86_64', 'i86pc']:
+        return 'amd64'
+    if machine in ['sun4v', 'sun4u']:
+        return 'sparcv9'
+    if machine == 'i386' and get_os() == 'darwin':
+        try:
+            # Support for Snow Leopard and earlier version of MacOSX
+            if subprocess.check_output(['sysctl', '-n', 'hw.cpu64bit_capable']).strip() == '1':
+                return 'amd64'
+        except OSError:
+            # sysctl is not available
+            pass
+    abort('unknown or unsupported architecture: os=' + get_os() + ', machine=' + machine)
+
 def _loadSuite(mxDir, primary=False):
     """
     Load a suite from 'mxDir'.
--- a/src/share/vm/prims/jvm.cpp	Tue Sep 02 19:01:01 2014 -0700
+++ b/src/share/vm/prims/jvm.cpp	Tue Sep 02 19:23:43 2014 -0700
@@ -391,6 +391,23 @@
 JVM_END
 
 
+/*
+ * Return the temporary directory that the VM uses for the attach
+ * and perf data files.
+ *
+ * It is important that this directory is well-known and the
+ * same for all VM instances. It cannot be affected by configuration
+ * variables such as java.io.tmpdir.
+ */
+JVM_ENTRY(jstring, JVM_GetTemporaryDirectory(JNIEnv *env))
+  JVMWrapper("JVM_GetTemporaryDirectory");
+  HandleMark hm(THREAD);
+  const char* temp_dir = os::get_temp_directory();
+  Handle h = java_lang_String::create_from_platform_dependent_str(temp_dir, CHECK_NULL);
+  return (jstring) JNIHandles::make_local(env, h());
+JVM_END
+
+
 // java.lang.Runtime /////////////////////////////////////////////////////////////////////////
 
 extern volatile jint vm_created;
--- a/src/share/vm/prims/jvm.h	Tue Sep 02 19:01:01 2014 -0700
+++ b/src/share/vm/prims/jvm.h	Tue Sep 02 19:23:43 2014 -0700
@@ -1482,6 +1482,9 @@
 JNIEXPORT jobject JNICALL
 JVM_InitAgentProperties(JNIEnv *env, jobject agent_props);
 
+JNIEXPORT jstring JNICALL
+JVM_GetTemporaryDirectory(JNIEnv *env);
+
 /* Generics reflection support.
  *
  * Returns information about the given class's EnclosingMethod