# HG changeset patch # User Stefan Anzinger # Date 1409711023 25200 # Node ID 2110fe2b72847203d2254399fa51f7dd995fbca2 # Parent 790e5e5072a2232bbc6ddda32204078c846d0519# Parent 66bf28082a142ad04f45dfa84cb84ca3ea620584 Merge diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java 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 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); diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java 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 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 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 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) { diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- 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 names, ArrayList list1, ArrayList list2) { + if (list1.isEmpty() && list2.isEmpty()) { + return new long[0]; + } + if (pfo != null) { + List fields = Arrays.asList(pfo.getOrderedFieldNames(input)); + long[] offsets = new long[fields.size()]; + assert list1.size() + list2.size() == fields.size(); + for (Map.Entry 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 successorOffsets = new ArrayList<>(); public final ArrayList successorListOffsets = new ArrayList<>(); public final HashMap types = new HashMap<>(); - public final HashMap names = new HashMap<>(); public final HashSet 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 { + 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 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; diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java --- 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 { @@ -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; + } + }; } diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodePosIterator.java --- /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 { + Position nextPosition(); +} \ No newline at end of file diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterable.java --- 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 { - /** - * 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; - } - }; -} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterator.java --- 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 { +public class NodeRefIterator implements NodePosIterator { public static final NodeRefIterator Empty = new NodeRefIterator(0, 0, false); diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java --- 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 diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java --- 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(); diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java --- 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()) { diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeGenerator.java --- 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 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 nodeFields, List 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); diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeProcessor.java --- 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 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 Bug 367599. @@ -166,9 +181,9 @@ return true; } } - if (t.getCause() != null) { - return isBug367599(t.getCause()); - } + } + if (t.getCause() != null) { + return isBug367599(t.getCause()); } return false; } diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java --- 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()) { diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java 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 duplicatedNodes, Deque 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); diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java --- 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 distinctValueAndConditionInputs(Node n) { ArrayList 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); diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java --- 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); diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java --- 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(); diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java --- 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); diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java --- 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) { diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.truffle.test/sl/TestCompilationThreshold.sl --- /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))); +} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.truffle.test/sl/TestInliningMaxCallerSize.sl --- /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"); +} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SLTruffleGraalTestSuite.java --- /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() { + } +} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLCallUntilOptimizedBuiltin.java --- /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 + * waitForOptimization(function) 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; + } +} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLDisableSplittingBuiltin.java --- /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; + } + +} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLGenerateDummyNodesBuiltin.java --- /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; + } + + } + +} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLGetOptionBuiltin.java --- /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; + } + +} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLGraalRuntimeBuiltin.java --- /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 findDuplicateCallTargets(OptimizedCallTarget originalCallTarget) { + final Set 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 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 findCallsTo(RootNode root, OptimizedCallTarget originalCallTarget) { + final Set 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; + } +} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLIsInlinedBuiltin.java --- /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 true 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 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; + } + } +} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLIsOptimizedBuiltin.java --- /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; + } +} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLSetOptionBuiltin.java --- /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; + } + +} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLWaitForOptimizationBuiltin.java --- /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); + } + +} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java --- 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); diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java --- 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) { diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java --- 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); diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java --- 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 { - 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> builtins = new ArrayList<>(); + + public static void installBuiltin(NodeFactory 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 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 { diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLAssertionError.java --- /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 diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLException.java --- 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 stackTrace = new ArrayList<>(); + Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor() { + 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; } } diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertFalseBuiltin.java --- /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 false and throws an {@link AssertionError} if the value + * was true. + */ +@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); + } + +} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertTrueBuiltin.java --- /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 true and throws an {@link AssertionError} if the value + * was false. + */ +@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); + } + +} diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java --- 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 diff -r 790e5e5072a2 -r 2110fe2b7284 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java --- 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 factory) { + public void installBuiltin(NodeFactory 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 diff -r 790e5e5072a2 -r 2110fe2b7284 make/bsd/makefiles/mapfile-vers-debug --- 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 diff -r 790e5e5072a2 -r 2110fe2b7284 make/bsd/makefiles/mapfile-vers-product --- 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 diff -r 790e5e5072a2 -r 2110fe2b7284 make/linux/makefiles/mapfile-vers-debug --- 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; diff -r 790e5e5072a2 -r 2110fe2b7284 make/linux/makefiles/mapfile-vers-product --- 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; diff -r 790e5e5072a2 -r 2110fe2b7284 make/solaris/makefiles/mapfile-vers --- 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; diff -r 790e5e5072a2 -r 2110fe2b7284 mx/mx_graal.py --- 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 = { diff -r 790e5e5072a2 -r 2110fe2b7284 mx/projects --- 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 diff -r 790e5e5072a2 -r 2110fe2b7284 mxtool/mx.py --- 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'. diff -r 790e5e5072a2 -r 2110fe2b7284 src/share/vm/prims/jvm.cpp --- 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; diff -r 790e5e5072a2 -r 2110fe2b7284 src/share/vm/prims/jvm.h --- 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