# HG changeset patch # User Stefan Anzinger # Date 1409273377 25200 # Node ID e4cfc9ea2bd343c86a92f68ec4058f8114f0cc47 # Parent c9c416d90a4eb6a286fe0858e3b493f2a6bc120a# Parent 9cf849d5b3f9bc090ffb92b26dcaec5016da78cb Merge diff -r c9c416d90a4e -r e4cfc9ea2bd3 CHANGELOG.md --- a/CHANGELOG.md Thu Aug 28 17:15:23 2014 -0700 +++ b/CHANGELOG.md Thu Aug 28 17:49:37 2014 -0700 @@ -5,7 +5,7 @@ * ... ### Truffle -* ... +* Added TruffleRuntime#getCallTargets() to get all call targets that were created and are still referenced. ## Version 0.4 19-Aug-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/graal-0.4) diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Thu Aug 28 17:49:37 2014 -0700 @@ -275,63 +275,63 @@ protected AMD64Arithmetic getOp(ValueNode operation, Access access) { Kind memoryKind = getMemoryKind(access); - if (operation.getClass() == IntegerAddNode.getGenClass()) { + if (operation.getNodeClass().is(IntegerAddNode.class)) { switch (memoryKind) { case Int: return IADD; case Long: return LADD; } - } else if (operation.getClass() == FloatAddNode.getGenClass()) { + } else if (operation.getNodeClass().is(FloatAddNode.class)) { switch (memoryKind) { case Float: return FADD; case Double: return DADD; } - } else if (operation.getClass() == AndNode.getGenClass()) { + } else if (operation.getNodeClass().is(AndNode.class)) { switch (memoryKind) { case Int: return IAND; case Long: return LAND; } - } else if (operation.getClass() == OrNode.getGenClass()) { + } else if (operation.getNodeClass().is(OrNode.class)) { switch (memoryKind) { case Int: return IOR; case Long: return LOR; } - } else if (operation.getClass() == XorNode.getGenClass()) { + } else if (operation.getNodeClass().is(XorNode.class)) { switch (memoryKind) { case Int: return IXOR; case Long: return LXOR; } - } else if (operation.getClass() == IntegerSubNode.getGenClass()) { + } else if (operation.getNodeClass().is(IntegerSubNode.class)) { switch (memoryKind) { case Int: return ISUB; case Long: return LSUB; } - } else if (operation.getClass() == FloatSubNode.getGenClass()) { + } else if (operation.getNodeClass().is(FloatSubNode.class)) { switch (memoryKind) { case Float: return FSUB; case Double: return DSUB; } - } else if (operation.getClass() == IntegerMulNode.getGenClass()) { + } else if (operation.getNodeClass().is(IntegerMulNode.class)) { switch (memoryKind) { case Int: return IMUL; case Long: return LMUL; } - } else if (operation.getClass() == FloatMulNode.getGenClass()) { + } else if (operation.getNodeClass().is(FloatMulNode.class)) { switch (memoryKind) { case Float: return FMUL; diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/DominatorOptimizationProblem.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/DominatorOptimizationProblem.java Thu Aug 28 17:49:37 2014 -0700 @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2014, 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.compiler.common.cfg; + +import java.util.*; +import java.util.stream.*; + +/** + * This class represents a dominator tree problem, i.e. a problem which can be solved by traversing + * the dominator (sub-)tree. + * + * @param An enum that describes the flags that can be associated with a block. + * @param An arbitrary cost type that is associated with a block. It is intended to carry + * information needed to calculate the solution. Note that {@code C} should not contain + * boolean flags. Use an enum entry in {@code E} instead. + */ +public abstract class DominatorOptimizationProblem, C> { + + private List> blocks; + private EnumMap flags; + private BlockMap costs; + + protected DominatorOptimizationProblem(Class flagType, AbstractControlFlowGraph cfg) { + this.blocks = cfg.getBlocks(); + flags = new EnumMap<>(flagType); + costs = new BlockMap<>(cfg); + assert verify(blocks); + } + + private static boolean verify(List> blocks) { + for (int i = 0; i < blocks.size(); i++) { + AbstractBlock block = blocks.get(i); + if (i != block.getId()) { + assert false : String.format("Id index mismatch @ %d vs. %s.getId()==%d", i, block, block.getId()); + return false; + } + } + return true; + } + + public final List> getBlocks() { + return blocks; + } + + public final AbstractBlock getBlockForId(int id) { + AbstractBlock block = blocks.get(id); + assert block.getId() == id : "wrong block-to-id mapping"; + return block; + } + + /** + * Sets a flag for a block. + */ + public final void set(E flag, AbstractBlock block) { + BitSet bitSet = flags.get(flag); + if (bitSet == null) { + bitSet = new BitSet(blocks.size()); + flags.put(flag, bitSet); + } + bitSet.set(block.getId()); + } + + /** + * Checks whether a flag is set for a block. + */ + public final boolean get(E flag, AbstractBlock block) { + BitSet bitSet = flags.get(flag); + return bitSet == null ? false : bitSet.get(block.getId()); + } + + /** + * Returns a {@linkplain Stream} of blocks for which {@code flag} is set. + */ + public final Stream> stream(E flag) { + return getBlocks().stream().filter(block -> get(flag, block)); + } + + /** + * Returns the cost object associated with {@code block}. Might return {@code null} if not set. + */ + public final C getCost(AbstractBlock block) { + C cost = costs.get(block); + return cost; + } + + /** + * Sets the cost for a {@code block}. + */ + public final void setCost(AbstractBlock block, C cost) { + costs.put(block, cost); + } + + /** + * Sets {@code flag} for all blocks along the dominator path from {@code block} to the root + * until a block it finds a block where {@code flag} is already set. + */ + public final void setDominatorPath(E flag, AbstractBlock block) { + BitSet bitSet = flags.get(flag); + if (bitSet == null) { + bitSet = new BitSet(blocks.size()); + flags.put(flag, bitSet); + } + for (AbstractBlock b = block; b != null && !bitSet.get(b.getId()); b = b.getDominator()) { + // mark block + bitSet.set(b.getId()); + } + } + + /** + * Returns a {@link Stream} of flags associated with {@code block}. + */ + public final Stream getFlagsForBlock(AbstractBlock block) { + return getFlags().stream().filter(flag -> get(flag, block)); + } + + /** + * Returns the {@link Set} of flags that can be set for this + * {@linkplain DominatorOptimizationProblem problem}. + */ + public final Set getFlags() { + return flags.keySet(); + } + + /** + * Returns the name of a flag. + */ + public String getName(E flag) { + return flag.toString(); + } +} \ No newline at end of file diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PrintableCFG.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PrintableCFG.java Thu Aug 28 17:49:37 2014 -0700 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, 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.compiler.common.cfg; + +import java.util.*; +import java.util.function.*; + +/** + * Represents a control-flow graph where each node can be annotated with arbitrary property pairs of + * the form ({@linkplain String name}, {@linkplain String value}). + */ +public interface PrintableCFG { + + List> getBlocks(); + + /** + * Applies {@code action} to all extra property pairs (name, value) of {@code block}. + * + * @param block a block from {@link #getBlocks()}. + * @param action a {@link BiConsumer consumer}. + */ + default void forEachPropertyPair(AbstractBlock block, BiConsumer action) { + // no extra properties per default + } +} diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PrintableDominatorOptimizationProblem.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PrintableDominatorOptimizationProblem.java Thu Aug 28 17:49:37 2014 -0700 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, 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.compiler.common.cfg; + +import java.util.function.*; + +/** + * A {@linkplain PrintableCFG printable} {@link DominatorOptimizationProblem}. + */ +public abstract class PrintableDominatorOptimizationProblem, C extends PropertyConsumable> extends DominatorOptimizationProblem implements PrintableCFG { + + protected PrintableDominatorOptimizationProblem(Class keyType, AbstractControlFlowGraph cfg) { + super(keyType, cfg); + } + + public void forEachPropertyPair(AbstractBlock block, BiConsumer action) { + // for each flag + getFlags().forEach(flag -> ((BiConsumer) (name, value) -> action.accept(name, value ? "true" : "false")).accept(getName(flag), get(flag, block))); + // for each property + C cost = getCost(block); + if (cost != null) { + cost.forEachProperty((name, value) -> action.accept(name, value)); + } + } +} \ No newline at end of file diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PropertyConsumable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PropertyConsumable.java Thu Aug 28 17:49:37 2014 -0700 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014, 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.compiler.common.cfg; + +import java.util.function.*; + +public interface PropertyConsumable { + + void forEachProperty(BiConsumer action); +} diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Thu Aug 28 17:49:37 2014 -0700 @@ -189,11 +189,7 @@ throw new AssertionError(String.format("Node subclass %s requires %s annotation", c.getName(), NodeClass.class.getSimpleName())); } if (!Modifier.isAbstract(c.getModifiers())) { - try { - Class.forName(c.getName().replace('$', '_') + "Gen"); - } catch (ClassNotFoundException e) { - throw new AssertionError(String.format("Missing generated Node class %s", c.getName() + "Gen")); - } + NodeClass.get(c).getGenClass(); } } } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu Aug 28 17:49:37 2014 -0700 @@ -41,6 +41,7 @@ import com.oracle.graal.debug.internal.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.constopt.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; @@ -256,6 +257,15 @@ throw Debug.handle(e); } + if (ConstantLoadOptimization.Options.ConstantLoadOptimization.getValue()) { + try (Scope s = Debug.scope("ConstantLoadOptimization", lir)) { + ConstantLoadOptimization.optimize(lirGenRes.getLIR(), lirGen); + Debug.dump(lir, "After constant load optimization"); + } catch (Throwable e) { + throw Debug.handle(e); + } + } + try (Scope s = Debug.scope("Allocator", nodeLirGen)) { if (backend.shouldAllocateRegisters()) { new LinearScan(target, lir, frameMap).allocate(); diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java Thu Aug 28 17:49:37 2014 -0700 @@ -151,8 +151,22 @@ this(null, name, singleUser); } + /** + * Gets the {@link Node} class instantiated for a given canonical {@link Node} class depending + * on whether or not generated node classes are enabled. + */ + @SuppressWarnings("unchecked") + private static Class asInstantiatedClass(Class nodeClass) { + if (nodeClass != null && Node.USE_GENERATED_NODES) { + Class res = (Class) NodeClass.get(nodeClass).getGenClass(); + assert res != null : nodeClass; + return res; + } + return nodeClass; + } + public MatchPattern(Class nodeClass, String name, boolean singleUser) { - this.nodeClass = nodeClass; + this.nodeClass = asInstantiatedClass(nodeClass); this.name = name; this.singleUser = singleUser; this.patterns = EMPTY_PATTERNS; @@ -161,7 +175,7 @@ private MatchPattern(Class nodeClass, String name, boolean singleUser, MatchPattern[] patterns, Position[] inputs) { assert inputs == null || inputs.length == patterns.length; - this.nodeClass = nodeClass; + this.nodeClass = asInstantiatedClass(nodeClass); this.name = name; this.singleUser = singleUser; this.patterns = patterns; diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java Thu Aug 28 17:49:37 2014 -0700 @@ -144,4 +144,9 @@ public String getName() { return name; } + + @Override + public String toString() { + return pattern.toString(); + } } diff -r c9c416d90a4e -r e4cfc9ea2bd3 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 Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Thu Aug 28 17:49:37 2014 -0700 @@ -42,12 +42,12 @@ /** * The set of nodes in the graph, ordered by {@linkplain #register(Node) registration} time. */ - private Node[] nodes; + Node[] nodes; /** * The number of valid entries in {@link #nodes}. */ - private int nodesSize; + int nodesSize; /** * Records the modification count for nodes. This is only used in assertions. @@ -562,56 +562,6 @@ return new Mark(this); } - private class NodeIterator implements Iterator { - - private int index; - - public NodeIterator() { - this(0); - } - - public NodeIterator(int index) { - this.index = index - 1; - forward(); - } - - private void forward() { - if (index < nodesSize) { - do { - index++; - } while (index < nodesSize && nodes[index] == null); - } - } - - @Override - public boolean hasNext() { - checkForDeletedNode(); - return index < nodesSize; - } - - private void checkForDeletedNode() { - if (index < nodesSize) { - while (index < nodesSize && nodes[index] == null) { - index++; - } - } - } - - @Override - public Node next() { - try { - return nodes[index]; - } finally { - forward(); - } - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - /** * Returns an {@link Iterable} providing all nodes added since the last {@link Graph#getMark() * mark}. @@ -622,7 +572,7 @@ @Override public Iterator iterator() { - return new NodeIterator(index); + return new GraphNodeIterator(Graph.this, index); } }; } @@ -637,7 +587,7 @@ @Override public Iterator iterator() { - return new NodeIterator(); + return new GraphNodeIterator(Graph.this); } @Override @@ -658,7 +608,7 @@ } } - private static final Node PLACE_HOLDER = USE_GENERATED_NODES ? new Graph_PlaceHolderNodeGen() : new PlaceHolderNode(); + static final Node PLACE_HOLDER = USE_GENERATED_NODES ? new Graph_PlaceHolderNodeGen() : new PlaceHolderNode(); /** * When the percent of live nodes in {@link #nodes} fall below this number, a call to @@ -709,107 +659,6 @@ return true; } - private static class TypedNodeIterator implements Iterator { - - private final Graph graph; - private final int[] ids; - private final Node[] current; - - private int currentIdIndex; - private boolean needsForward; - - public TypedNodeIterator(NodeClass clazz, Graph graph) { - this.graph = graph; - ids = clazz.iterableIds(); - currentIdIndex = 0; - current = new Node[ids.length]; - Arrays.fill(current, PLACE_HOLDER); - needsForward = true; - } - - private Node findNext() { - if (needsForward) { - forward(); - } else { - Node c = current(); - Node afterDeleted = skipDeleted(c); - if (afterDeleted == null) { - needsForward = true; - } else if (c != afterDeleted) { - setCurrent(afterDeleted); - } - } - if (needsForward) { - return null; - } - return current(); - } - - private static Node skipDeleted(Node node) { - Node n = node; - while (n != null && n.isDeleted()) { - n = n.typeCacheNext; - } - return n; - } - - private void forward() { - needsForward = false; - int startIdx = currentIdIndex; - while (true) { - Node next; - if (current() == PLACE_HOLDER) { - next = graph.getStartNode(ids[currentIdIndex]); - } else { - next = current().typeCacheNext; - } - next = skipDeleted(next); - if (next == null) { - currentIdIndex++; - if (currentIdIndex >= ids.length) { - currentIdIndex = 0; - } - if (currentIdIndex == startIdx) { - needsForward = true; - return; - } - } else { - setCurrent(next); - break; - } - } - } - - private Node current() { - return current[currentIdIndex]; - } - - private void setCurrent(Node n) { - current[currentIdIndex] = n; - } - - @Override - public boolean hasNext() { - return findNext() != null; - } - - @Override - @SuppressWarnings("unchecked") - public T next() { - Node result = findNext(); - if (result == null) { - throw new NoSuchElementException(); - } - needsForward = true; - return (T) result; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - /** * Returns an {@link Iterable} providing all the live nodes whose type is compatible with * {@code type}. @@ -823,7 +672,7 @@ @Override public Iterator iterator() { - return new TypedNodeIterator<>(nodeClass, Graph.this); + return new TypedGraphNodeIterator<>(nodeClass, Graph.this); } }; } @@ -838,7 +687,7 @@ return getNodes(type).iterator().hasNext(); } - private Node getStartNode(int iterableId) { + Node getStartNode(int iterableId) { Node start = nodeCacheFirst.size() <= iterableId ? null : nodeCacheFirst.get(iterableId); return start; } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphNodeIterator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphNodeIterator.java Thu Aug 28 17:49:37 2014 -0700 @@ -0,0 +1,78 @@ +/* + * 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.*; + +/** + * Iterates over the nodes in a given graph. + */ +class GraphNodeIterator implements Iterator { + + private final Graph graph; + private int index; + + public GraphNodeIterator(Graph graph) { + this(graph, 0); + } + + public GraphNodeIterator(Graph graph, int index) { + this.graph = graph; + this.index = index - 1; + forward(); + } + + private void forward() { + if (index < graph.nodesSize) { + do { + index++; + } while (index < graph.nodesSize && graph.nodes[index] == null); + } + } + + @Override + public boolean hasNext() { + checkForDeletedNode(); + return index < graph.nodesSize; + } + + private void checkForDeletedNode() { + while (index < graph.nodesSize && graph.nodes[index] == null) { + index++; + } + } + + @Override + public Node next() { + try { + return graph.nodes[index]; + } finally { + forward(); + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} \ No newline at end of file diff -r c9c416d90a4e -r e4cfc9ea2bd3 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 Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Thu Aug 28 17:49:37 2014 -0700 @@ -56,7 +56,7 @@ @NodeInfo public abstract class Node implements Cloneable, Formattable { - public final static boolean USE_GENERATED_NODES = Boolean.getBoolean("graal.useGeneratedNodes"); + public final static boolean USE_GENERATED_NODES = Boolean.parseBoolean(System.getProperty("graal.useGeneratedNodes", "true")); static final int DELETED_ID_START = -1000000000; static final int INITIAL_ID = -1; diff -r c9c416d90a4e -r e4cfc9ea2bd3 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 Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Thu Aug 28 17:49:37 2014 -0700 @@ -25,6 +25,7 @@ import static com.oracle.graal.graph.Graph.*; import static com.oracle.graal.graph.Node.*; import static com.oracle.graal.graph.util.CollectionsAccess.*; +import static java.lang.reflect.Modifier.*; import java.lang.reflect.*; import java.util.*; @@ -54,8 +55,7 @@ */ @SuppressWarnings("unchecked") public static NodeClass get(Class c) { - GeneratedNode gen = c.getAnnotation(GeneratedNode.class); - Class key = gen == null ? (Class) c : (Class) gen.value(); + Class key = (Class) c; NodeClass value = (NodeClass) allClasses.get(key); // The fact that {@link ConcurrentHashMap#put} and {@link ConcurrentHashMap#get} @@ -66,7 +66,19 @@ synchronized (GetNodeClassLock) { value = (NodeClass) allClasses.get(key); if (value == null) { - value = new NodeClass(key); + GeneratedNode gen = c.getAnnotation(GeneratedNode.class); + if (gen != null) { + Class originalNodeClass = (Class) gen.value(); + value = (NodeClass) allClasses.get(originalNodeClass); + assert value != null; + if (value.genClass == null) { + value.genClass = (Class) c; + } else { + assert value.genClass == c; + } + } else { + value = new NodeClass(key); + } Object old = allClasses.putIfAbsent(key, value); assert old == null : old + " " + key; } @@ -96,6 +108,13 @@ private final EnumSet allowedUsageTypes; private int[] iterableIds; + /** + * The {@linkplain GeneratedNode generated} node class denoted by this object. This value is + * lazily initialized to avoid class initialization circularity issues. A sentinel value of + * {@code Node.class} is used to denote absence of a generated class. + */ + private Class genClass; + private static final DebugMetric ITERABLE_NODE_TYPES = Debug.metric("IterableNodeTypes"); private final DebugMetric nodeIterableCount; @@ -158,15 +177,12 @@ } String newNameTemplate = null; NodeInfo info = clazz.getAnnotation(NodeInfo.class); - if (info != null) { - if (!info.shortName().isEmpty()) { - newShortName = info.shortName(); - } - if (!info.nameTemplate().isEmpty()) { - newNameTemplate = info.nameTemplate(); - } - } else { - System.out.println("No NodeInfo for " + clazz); + assert info != null : "missing " + NodeInfo.class.getSimpleName() + " annotation on " + clazz; + if (!info.shortName().isEmpty()) { + newShortName = info.shortName(); + } + if (!info.nameTemplate().isEmpty()) { + newNameTemplate = info.nameTemplate(); } EnumSet newAllowedUsageTypes = EnumSet.noneOf(InputType.class); Class current = clazz; @@ -190,13 +206,19 @@ this.iterableId = nextIterableId++; List existingClasses = new LinkedList<>(); for (FieldIntrospection nodeClass : allClasses.values()) { + // There are duplicate entries in allClasses when using generated nodes + // hence the extra logic below guarded by USE_GENERATED_NODES if (clazz.isAssignableFrom(nodeClass.getClazz())) { - existingClasses.add((NodeClass) nodeClass); + if (!USE_GENERATED_NODES || !existingClasses.contains(nodeClass)) { + existingClasses.add((NodeClass) nodeClass); + } } if (nodeClass.getClazz().isAssignableFrom(clazz) && IterableNodeType.class.isAssignableFrom(nodeClass.getClazz())) { NodeClass superNodeClass = (NodeClass) nodeClass; - superNodeClass.iterableIds = Arrays.copyOf(superNodeClass.iterableIds, superNodeClass.iterableIds.length + 1); - superNodeClass.iterableIds[superNodeClass.iterableIds.length - 1] = this.iterableId; + if (!USE_GENERATED_NODES || !containsId(this.iterableId, superNodeClass.iterableIds)) { + superNodeClass.iterableIds = Arrays.copyOf(superNodeClass.iterableIds, superNodeClass.iterableIds.length + 1); + superNodeClass.iterableIds[superNodeClass.iterableIds.length - 1] = this.iterableId; + } } } int[] ids = new int[existingClasses.size() + 1]; @@ -214,6 +236,39 @@ nodeIterableCount = Debug.metric("NodeIterable_%s", shortName); } + /** + * Gets the {@linkplain GeneratedNode generated} node class (if any) described by the object. + */ + @SuppressWarnings("unchecked") + public Class getGenClass() { + if (USE_GENERATED_NODES) { + if (genClass == null) { + if (!isAbstract(getClazz().getModifiers())) { + String genClassName = getClazz().getName().replace('$', '_') + "Gen"; + try { + genClass = (Class) Class.forName(genClassName); + } catch (ClassNotFoundException e) { + throw new GraalInternalError("Could not find generated class " + genClassName + " for " + getClazz()); + } + } else { + // Sentinel value denoting no generated class + genClass = Node.class; + } + } + return genClass.equals(Node.class) ? null : genClass; + } + return null; + } + + private static boolean containsId(int iterableId, int[] iterableIds) { + for (int i : iterableIds) { + if (i == iterableId) { + return true; + } + } + return false; + } + @Override protected void rescanFieldOffsets(CalcOffset calc) { FieldScanner scanner = new FieldScanner(calc); @@ -234,14 +289,14 @@ fieldTypes.putAll(scanner.fieldTypes); } - private boolean isNodeClassFor(Node n) { - if (Node.USE_GENERATED_NODES) { - GeneratedNode gen = n.getClass().getAnnotation(GeneratedNode.class); - assert gen != null; - return gen.value() == getClazz(); - } else { - return n.getNodeClass().getClazz() == n.getClass(); - } + /** + * Determines if a given {@link Node} class is described by the {@link NodeClass} object. + * + * @param nodeClass a {@linkplain GeneratedNode non-generated} {@link Node} class + */ + public boolean is(Class nodeClass) { + assert nodeClass.getAnnotation(GeneratedNode.class) == null : "cannot test NodeClas against generated " + nodeClass; + return nodeClass == getClazz(); } public String shortName() { @@ -1214,7 +1269,7 @@ * @param newNode the node to which the inputs should be copied. */ public void copyInputs(Node node, Node newNode) { - assert isNodeClassFor(node) && isNodeClassFor(newNode); + assert node.getNodeClass() == this && newNode.getNodeClass() == this; int index = 0; while (index < directInputCount) { @@ -1236,7 +1291,7 @@ * @param newNode the node to which the successors should be copied. */ public void copySuccessors(Node node, Node newNode) { - assert isNodeClassFor(node) && isNodeClassFor(newNode); + assert node.getNodeClass() == this && newNode.getNodeClass() == this; int index = 0; while (index < directSuccessorCount) { @@ -1255,7 +1310,7 @@ } public boolean inputsEqual(Node node, Node other) { - assert isNodeClassFor(node) && isNodeClassFor(other); + assert node.getNodeClass() == this && other.getNodeClass() == this; int index = 0; while (index < directInputCount) { if (getNode(other, inputOffsets[index]) != getNode(node, inputOffsets[index])) { @@ -1274,7 +1329,7 @@ } public boolean successorsEqual(Node node, Node other) { - assert isNodeClassFor(node) && isNodeClassFor(other); + assert node.getNodeClass() == this && other.getNodeClass() == this; int index = 0; while (index < directSuccessorCount) { if (getNode(other, successorOffsets[index]) != getNode(node, successorOffsets[index])) { @@ -1293,7 +1348,7 @@ } public boolean inputContains(Node node, Node other) { - assert isNodeClassFor(node); + assert node.getNodeClass() == this; int index = 0; while (index < directInputCount) { @@ -1313,7 +1368,7 @@ } public boolean successorContains(Node node, Node other) { - assert isNodeClassFor(node); + assert node.getNodeClass() == this; int index = 0; while (index < directSuccessorCount) { diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/TypedGraphNodeIterator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/TypedGraphNodeIterator.java Thu Aug 28 17:49:37 2014 -0700 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2011, 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.*; + +class TypedGraphNodeIterator implements Iterator { + + private final Graph graph; + private final int[] ids; + private final Node[] current; + + private int currentIdIndex; + private boolean needsForward; + + public TypedGraphNodeIterator(NodeClass clazz, Graph graph) { + this.graph = graph; + ids = clazz.iterableIds(); + currentIdIndex = 0; + current = new Node[ids.length]; + Arrays.fill(current, Graph.PLACE_HOLDER); + needsForward = true; + } + + private Node findNext() { + if (needsForward) { + forward(); + } else { + Node c = current(); + Node afterDeleted = skipDeleted(c); + if (afterDeleted == null) { + needsForward = true; + } else if (c != afterDeleted) { + setCurrent(afterDeleted); + } + } + if (needsForward) { + return null; + } + return current(); + } + + private static Node skipDeleted(Node node) { + Node n = node; + while (n != null && n.isDeleted()) { + n = n.typeCacheNext; + } + return n; + } + + private void forward() { + needsForward = false; + int startIdx = currentIdIndex; + while (true) { + Node next; + if (current() == Graph.PLACE_HOLDER) { + next = graph.getStartNode(ids[currentIdIndex]); + } else { + next = current().typeCacheNext; + } + next = skipDeleted(next); + if (next == null) { + currentIdIndex++; + if (currentIdIndex >= ids.length) { + currentIdIndex = 0; + } + if (currentIdIndex == startIdx) { + needsForward = true; + return; + } + } else { + setCurrent(next); + break; + } + } + } + + private Node current() { + return current[currentIdIndex]; + } + + private void setCurrent(Node n) { + current[currentIdIndex] = n; + } + + @Override + public boolean hasNext() { + return findNext() != null; + } + + @Override + @SuppressWarnings("unchecked") + public T next() { + Node result = findNext(); + if (result == null) { + throw new NoSuchElementException(); + } + needsForward = true; + return (T) result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java Thu Aug 28 17:49:37 2014 -0700 @@ -146,8 +146,12 @@ private HotSpotNativeFunctionHandle createHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes) { HotSpotNativeFunctionPointer hs = (HotSpotNativeFunctionPointer) functionPointer; - InstalledCode code = installNativeFunctionStub(hs.value, returnType, argumentTypes); - return new HotSpotNativeFunctionHandle(code, hs.name, argumentTypes); + if (hs != null) { + InstalledCode code = installNativeFunctionStub(hs.value, returnType, argumentTypes); + return new HotSpotNativeFunctionHandle(code, hs.name, argumentTypes); + } else { + return null; + } } /** diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java Thu Aug 28 17:49:37 2014 -0700 @@ -31,9 +31,9 @@ @NodeInfo public abstract class WriteBarrier extends FixedWithNextNode implements Lowerable { - @Input ValueNode object; - @OptionalInput ValueNode value; - @OptionalInput(InputType.Association) LocationNode location; + @Input protected ValueNode object; + @OptionalInput protected ValueNode value; + @OptionalInput(InputType.Association) protected LocationNode location; private final boolean precise; public WriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise) { diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Aug 28 17:49:37 2014 -0700 @@ -1334,7 +1334,7 @@ frameState.clearNonLiveLocals(currentBlock, liveness, false); } if (lastInstr instanceof StateSplit) { - if (lastInstr.getClass() == BeginNode.getGenClass()) { + if (lastInstr.getNodeClass().is(BeginNode.class)) { // BeginNodes do not need a frame state } else { StateSplit stateSplit = (StateSplit) lastInstr; diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_ddiv.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_ddiv.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_ddiv.java Thu Aug 28 17:49:37 2014 -0700 @@ -39,4 +39,8 @@ runTest("test", 311.0D, 10D); } + @Test + public void run1() throws Throwable { + runTest("test", 311.0D, 0D); + } } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_fdiv.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_fdiv.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_fdiv.java Thu Aug 28 17:49:37 2014 -0700 @@ -39,4 +39,8 @@ runTest("test", 311.0f, 10f); } + @Test + public void run1() throws Throwable { + runTest("test", 311.0f, 0f); + } } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java Thu Aug 28 17:49:37 2014 -0700 @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2014, 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.lir.constopt; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRValueUtil.*; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.MoveOp; +import com.oracle.graal.lir.constopt.ConstantTree.Flags; +import com.oracle.graal.lir.constopt.ConstantTree.NodeCost; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.options.*; + +/** + * This optimization tries to improve the handling of constants by replacing a single definition of + * a constant, which is potentially scheduled into a block with high probability, with one or more + * definitions in blocks with a lower probability. + */ +public class ConstantLoadOptimization { + + public static class Options { + // @formatter:off + @Option(help = "Enable constant load optimization.") + public static final OptionValue ConstantLoadOptimization = new OptionValue<>(true); + // @formatter:on + } + + public static void optimize(LIR lir, LIRGeneratorTool lirGen) { + new ConstantLoadOptimization(lir, lirGen).apply(); + } + + private LIR lir; + private LIRGeneratorTool lirGen; + private VariableMap map; + private BitSet phiConstants; + private BitSet defined; + private BlockMap> blockMap; + private BlockMap insertionBuffers; + + private static DebugMetric constantsTotal = Debug.metric("ConstantLoadOptimization[total]"); + private static DebugMetric phiConstantsSkipped = Debug.metric("ConstantLoadOptimization[PhisSkipped]"); + private static DebugMetric singleUsageConstantsSkipped = Debug.metric("ConstantLoadOptimization[SingleUsageSkipped]"); + private static DebugMetric usageAtDefinitionSkipped = Debug.metric("ConstantLoadOptimization[UsageAtDefinitionSkipped]"); + private static DebugMetric materializeAtDefinitionSkipped = Debug.metric("ConstantLoadOptimization[MaterializeAtDefinitionSkipped]"); + private static DebugMetric constantsOptimized = Debug.metric("ConstantLoadOptimization[optimized]"); + + private ConstantLoadOptimization(LIR lir, LIRGeneratorTool lirGen) { + this.lir = lir; + this.lirGen = lirGen; + this.map = new VariableMap<>(); + this.phiConstants = new BitSet(); + this.defined = new BitSet(); + this.insertionBuffers = new BlockMap<>(lir.getControlFlowGraph()); + this.blockMap = new BlockMap<>(lir.getControlFlowGraph()); + } + + private void apply() { + try (Indent indent = Debug.logAndIndent("ConstantLoadOptimization")) { + try (Scope s = Debug.scope("BuildDefUseTree")) { + // build DefUseTree + lir.getControlFlowGraph().getBlocks().forEach(this::analyzeBlock); + // remove all with only one use + map.filter(t -> { + if (t.usageCount() > 1) { + return true; + } else { + singleUsageConstantsSkipped.increment(); + return false; + } + }); + // collect block map + map.forEach(tree -> tree.forEach(this::addUsageToBlockMap)); + } catch (Throwable e) { + throw Debug.handle(e); + } + + try (Scope s = Debug.scope("BuildConstantTree")) { + // create ConstantTree + map.forEach(this::createConstantTree); + + // insert moves, delete null instructions and reset instruction ids + lir.getControlFlowGraph().getBlocks().forEach(this::rewriteBlock); + } catch (Throwable e) { + throw Debug.handle(e); + } + } + } + + private static boolean isConstantLoad(LIRInstruction inst) { + if (!(inst instanceof MoveOp)) { + return false; + } + MoveOp move = (MoveOp) inst; + return isConstant(move.getInput()) && isVariable(move.getResult()); + } + + private void addUsageToBlockMap(UseEntry entry) { + AbstractBlock block = entry.getBlock(); + List list = blockMap.get(block); + if (list == null) { + list = new ArrayList<>(); + blockMap.put(block, list); + } + list.add(entry); + } + + /** + * Collects def-use information for a {@code block}. + */ + private void analyzeBlock(AbstractBlock block) { + try (Indent indent = Debug.logAndIndent("Block: %s", block)) { + + InstructionValueConsumer loadConsumer = new InstructionValueConsumer() { + @Override + public void visitValue(LIRInstruction instruction, Value value) { + if (isVariable(value)) { + Variable var = (Variable) value; + + if (!phiConstants.get(var.index)) { + if (!defined.get(var.index)) { + defined.set(var.index); + if (isConstantLoad(instruction)) { + Debug.log("constant load: %s", instruction); + map.put(var, new DefUseTree(instruction, block)); + constantsTotal.increment(); + } + } else { + // Variable is redefined, this only happens for constant loads + // introduced by phi resolution -> ignore. + DefUseTree removed = map.remove(var); + if (removed != null) { + phiConstantsSkipped.increment(); + } + phiConstants.set(var.index); + Debug.log(3, "Removing phi variable: %s", var); + } + } else { + assert defined.get(var.index) : "phi but not defined? " + var; + } + + } + } + + }; + + ValuePositionProcedure useProcedure = new ValuePositionProcedure() { + @Override + public void doValue(LIRInstruction instruction, ValuePosition position) { + Value value = position.get(instruction); + if (isVariable(value)) { + Variable var = (Variable) value; + if (!phiConstants.get(var.index)) { + DefUseTree tree = map.get(var); + if (tree != null) { + tree.addUsage(block, instruction, position); + Debug.log("usage of %s : %s", var, instruction); + } + } + } + } + + }; + + int opId = 0; + for (LIRInstruction inst : lir.getLIRforBlock(block)) { + // set instruction id to the index in the lir instruction list + inst.setId(opId++); + inst.visitEachOutput(loadConsumer); + inst.forEachInput(useProcedure); + inst.forEachAlive(useProcedure); + + } + } + } + + /** + * Creates the dominator tree and searches for an solution. + */ + private void createConstantTree(DefUseTree tree) { + ConstantTree constTree = new ConstantTree(lir.getControlFlowGraph(), tree); + constTree.set(Flags.SUBTREE, tree.getBlock()); + tree.forEach(u -> constTree.set(Flags.USAGE, u.getBlock())); + + if (constTree.get(Flags.USAGE, tree.getBlock())) { + // usage in the definition block -> no optimization + usageAtDefinitionSkipped.increment(); + return; + } + + constTree.markBlocks(); + + NodeCost cost = ConstantTreeAnalyzer.analyze(constTree, tree.getBlock()); + int usageCount = cost.getUsages().size(); + assert usageCount == tree.usageCount() : "Usage count differs: " + usageCount + " vs. " + tree.usageCount(); + + if (Debug.isLogEnabled()) { + try (Indent i = Debug.logAndIndent("Variable: %s, Block: %s, prob.: %f", tree.getVariable(), tree.getBlock(), tree.getBlock().probability())) { + Debug.log("Usages result: %s", cost); + } + + } + + if (cost.getNumMaterializations() > 1 || cost.getBestCost() < tree.getBlock().probability()) { + try (Scope s = Debug.scope("CLOmodify", constTree); Indent i = Debug.logAndIndent("Replacing %s = %s", tree.getVariable(), tree.getConstant().toValueString())) { + // mark original load for removal + deleteInstruction(tree); + constantsOptimized.increment(); + + // collect result + createLoads(tree, constTree, tree.getBlock()); + + } catch (Throwable e) { + throw Debug.handle(e); + } + } else { + // no better solution found + materializeAtDefinitionSkipped.increment(); + } + Debug.dump(constTree, "ConstantTree for " + tree.getVariable()); + } + + private void createLoads(DefUseTree tree, ConstantTree constTree, AbstractBlock startBlock) { + Deque> worklist = new ArrayDeque<>(); + worklist.add(startBlock); + while (!worklist.isEmpty()) { + AbstractBlock block = worklist.pollLast(); + if (constTree.get(Flags.CANDIDATE, block)) { + constTree.set(Flags.MATERIALIZE, block); + // create and insert load + insertLoad(tree.getConstant(), tree.getVariable().getLIRKind(), block, constTree.getCost(block).getUsages()); + } else { + for (AbstractBlock dominated : block.getDominated()) { + if (constTree.isMarked(dominated)) { + worklist.addLast(dominated); + } + } + } + } + } + + private void insertLoad(Constant constant, LIRKind kind, AbstractBlock block, List usages) { + assert usages != null && usages.size() > 0 : String.format("No usages %s %s %s", constant, block, usages); + // create variable + Variable variable = lirGen.newVariable(kind); + // create move + LIRInstruction move = lir.getSpillMoveFactory().createMove(variable, constant); + // insert instruction + getInsertionBuffer(block).append(1, move); + Debug.log("new move (%s) and inserted in block %s", move, block); + // update usages + for (UseEntry u : usages) { + u.getPosition().set(u.getInstruction(), variable); + Debug.log("patched instruction %s", u.getInstruction()); + } + } + + /** + * Inserts the constant loads created in {@link #createConstantTree} and deletes the original + * definition. + */ + private void rewriteBlock(AbstractBlock block) { + // insert moves + LIRInsertionBuffer buffer = insertionBuffers.get(block); + if (buffer != null) { + assert buffer.initialized() : "not initialized?"; + buffer.finish(); + } + + // delete instructions + List instructions = lir.getLIRforBlock(block); + boolean hasDead = false; + for (LIRInstruction inst : instructions) { + if (inst == null) { + hasDead = true; + } else { + inst.setId(-1); + } + } + if (hasDead) { + // Remove null values from the list. + instructions.removeAll(Collections.singleton(null)); + } + } + + private void deleteInstruction(DefUseTree tree) { + AbstractBlock block = tree.getBlock(); + LIRInstruction instruction = tree.getInstruction(); + Debug.log("deleting instruction %s from block %s", instruction, block); + lir.getLIRforBlock(block).set(instruction.id(), null); + } + + private LIRInsertionBuffer getInsertionBuffer(AbstractBlock block) { + LIRInsertionBuffer insertionBuffer = insertionBuffers.get(block); + if (insertionBuffer == null) { + insertionBuffer = new LIRInsertionBuffer(); + insertionBuffers.put(block, insertionBuffer); + assert !insertionBuffer.initialized() : "already initialized?"; + List instructions = lir.getLIRforBlock(block); + insertionBuffer.init(instructions); + } + return insertionBuffer; + } +} diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTree.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTree.java Thu Aug 28 17:49:37 2014 -0700 @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2014, 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.lir.constopt; + +import java.util.*; +import java.util.function.*; + +import com.oracle.graal.compiler.common.cfg.*; + +/** + * Represents a dominator (sub-)tree for a constant definition. + */ +public class ConstantTree extends PrintableDominatorOptimizationProblem { + + public enum Flags { + SUBTREE, + USAGE, + MATERIALIZE, + CANDIDATE, + } + + /** + * Costs associated with a block. + */ + public static class NodeCost implements PropertyConsumable { + private List usages; + private double bestCost; + private int numMat; + + public NodeCost(double bestCost, List usages, int numMat) { + this.bestCost = bestCost; + this.usages = usages; + this.numMat = numMat; + } + + public void forEachProperty(BiConsumer action) { + action.accept("bestCost", Double.toString(getBestCost())); + action.accept("numMat", Integer.toString(getNumMaterializations())); + action.accept("numUsages", Integer.toString(usages.size())); + } + + public void addUsage(UseEntry usage) { + if (usages == null) { + usages = new ArrayList<>(); + } + usages.add(usage); + } + + public List getUsages() { + if (usages == null) { + Collections.emptyList(); + } + return usages; + } + + public double getBestCost() { + return bestCost; + } + + public int getNumMaterializations() { + return numMat; + } + + public void setBestCost(double cost) { + bestCost = cost; + } + + @Override + public String toString() { + return "NodeCost [bestCost=" + bestCost + ", numUsages=" + usages.size() + ", numMat=" + numMat + "]"; + } + } + + private final BlockMap> blockMap; + + public ConstantTree(AbstractControlFlowGraph cfg, DefUseTree tree) { + super(Flags.class, cfg); + this.blockMap = new BlockMap<>(cfg); + tree.forEach(u -> getOrInitList(u.getBlock()).add(u)); + } + + private List getOrInitList(AbstractBlock block) { + List list = blockMap.get(block); + if (list == null) { + list = new ArrayList<>(); + blockMap.put(block, list); + } + return list; + } + + public List getUsages(AbstractBlock block) { + List list = blockMap.get(block); + if (list == null) { + return Collections.emptyList(); + } + return Collections.unmodifiableList(list); + } + + /** + * Returns the cost object associated with {@code block}. If there is none, a new cost object is + * created. + */ + NodeCost getOrInitCost(AbstractBlock block) { + NodeCost cost = getCost(block); + if (cost == null) { + cost = new NodeCost(block.probability(), blockMap.get(block), 1); + setCost(block, cost); + } + return cost; + } + + @Override + public String getName(Flags type) { + switch (type) { + case USAGE: + return "hasUsage"; + case SUBTREE: + return "inSubtree"; + case MATERIALIZE: + return "materialize"; + case CANDIDATE: + return "candidate"; + } + return super.getName(type); + } + + @Override + public void forEachPropertyPair(AbstractBlock block, BiConsumer action) { + if (get(Flags.SUBTREE, block) && (block.getDominator() == null || !get(Flags.SUBTREE, block.getDominator()))) { + action.accept("hasDefinition", "true"); + } + super.forEachPropertyPair(block, action); + } + + public long subTreeSize() { + return stream(Flags.SUBTREE).count(); + } + + public AbstractBlock getStartBlock() { + return stream(Flags.SUBTREE).findFirst().get(); + } + + public void markBlocks() { + stream(Flags.USAGE).forEach(block -> setDominatorPath(Flags.SUBTREE, block)); + } + + public boolean isMarked(AbstractBlock block) { + return get(Flags.SUBTREE, block); + } + + public boolean isLeafBlock(AbstractBlock block) { + return block.getDominated().stream().noneMatch(this::isMarked); + } + + public void setSolution(AbstractBlock block) { + set(Flags.MATERIALIZE, block); + } + + public int size() { + return getBlocks().size(); + } + + public void traverseTreeWhileTrue(AbstractBlock block, Predicate> action) { + assert block != null : "block must not be null!"; + if (action.test(block)) { + block.getDominated().stream().filter(this::isMarked).forEach(dominated -> traverseTreeWhileTrue(dominated, action)); + } + } + +} diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTreeAnalyzer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTreeAnalyzer.java Thu Aug 28 17:49:37 2014 -0700 @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2014, 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.lir.constopt; + +import java.util.*; + +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.lir.constopt.ConstantTree.Flags; +import com.oracle.graal.lir.constopt.ConstantTree.NodeCost; + +/** + * Analyzes a {@link ConstantTree} and marks potential materialization positions. + */ +public class ConstantTreeAnalyzer { + private final ConstantTree tree; + private final BitSet visited; + + public static NodeCost analyze(ConstantTree tree, AbstractBlock startBlock) { + try (Scope s = Debug.scope("ConstantTreeAnalyzer")) { + ConstantTreeAnalyzer analyzer = new ConstantTreeAnalyzer(tree); + analyzer.analyzeBlocks(startBlock); + return tree.getCost(startBlock); + } catch (Throwable e) { + throw Debug.handle(e); + } + } + + private ConstantTreeAnalyzer(ConstantTree tree) { + this.tree = tree; + this.visited = new BitSet(tree.size()); + } + + /** + * Queues all relevant blocks for {@linkplain #process processing}. + * + * This is a worklist-style algorithm because a (more elegant) recursive implementation may + * cause {@linkplain StackOverflowError stack overflows} on larger graphs. + * + * @param startBlock The start block of the dominator subtree. + */ + private void analyzeBlocks(AbstractBlock startBlock) { + Deque> worklist = new ArrayDeque<>(); + worklist.offerLast(startBlock); + while (!worklist.isEmpty()) { + AbstractBlock block = worklist.pollLast(); + try (Indent i = Debug.logAndIndent(3, "analyze: %s", block)) { + assert block != null : "worklist is empty!"; + assert isMarked(block) : "Block not part of the dominator tree: " + block; + + if (isLeafBlock(block)) { + Debug.log(3, "leaf block"); + leafCost(block); + continue; + } + + if (!visited.get(block.getId())) { + // if not yet visited (and not a leaf block) process all children first! + Debug.log(3, "not marked"); + worklist.offerLast(block); + List> children = block.getDominated(); + children.forEach(child -> filteredPush(worklist, child)); + visited.set(block.getId()); + } else { + Debug.log(3, "marked"); + // otherwise, process block + process(block); + } + } + } + } + + /** + * Calculates the cost of a {@code block}. It is assumed that all {@code children} have already + * been {@linkplain #process processed} + * + * @param block The block to be processed. + */ + private void process(AbstractBlock block) { + List usages = new ArrayList<>(); + double bestCost = 0; + int numMat = 0; + List> children = block.getDominated(); + assert children.stream().anyMatch(this::isMarked) : "no children? should have called leafCost(): " + block; + + // collect children costs + for (AbstractBlock child : children) { + if (isMarked(child)) { + NodeCost childCost = tree.getCost(child); + assert childCost != null : "Child with null cost? block: " + child; + usages.addAll(childCost.getUsages()); + numMat += childCost.getNumMaterializations(); + bestCost += childCost.getBestCost(); + } + } + assert numMat > 0 : "No materialization? " + numMat; + + // choose block + List usagesBlock = tree.getUsages(block); + double probabilityBlock = block.probability(); + + if (!usagesBlock.isEmpty() || shouldMaterializerInCurrentBlock(probabilityBlock, bestCost, numMat)) { + // mark current block as potential materialization position + usages.addAll(usagesBlock); + bestCost = probabilityBlock; + numMat = 1; + tree.set(Flags.CANDIDATE, block); + } else { + // stick with the current solution + } + + assert (new HashSet<>(usages)).size() == usages.size() : "doulbe entries? " + usages; + NodeCost nodeCost = new NodeCost(bestCost, usages, numMat); + tree.setCost(block, nodeCost); + } + + /** + * This is the cost function that decides whether a materialization should be inserted in the + * current block. + *

+ * Note that this function does not take into account if a materialization is required despite + * the probabilities (e.g. there are usages in the current block). + * + * @param probabilityBlock Probability of the current block. + * @param probabilityChildren Accumulated probability of the children. + * @param numMat Number of materializations along the subtrees. We use {@code numMat - 1} to + * insert materializations as late as possible if the probabilities are the same. + */ + private static boolean shouldMaterializerInCurrentBlock(double probabilityBlock, double probabilityChildren, int numMat) { + return probabilityBlock * Math.pow(0.9, numMat - 1) < probabilityChildren; + } + + private void filteredPush(Deque> worklist, AbstractBlock block) { + if (isMarked(block)) { + Debug.log(3, "adding %s to the worklist", block); + worklist.offerLast(block); + } + } + + private void leafCost(AbstractBlock block) { + tree.set(Flags.CANDIDATE, block); + tree.getOrInitCost(block); + } + + private boolean isMarked(AbstractBlock block) { + return tree.isMarked(block); + } + + private boolean isLeafBlock(AbstractBlock block) { + return tree.isLeafBlock(block); + } + +} diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/DefUseTree.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/DefUseTree.java Thu Aug 28 17:49:37 2014 -0700 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014, 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.lir.constopt; + +import java.util.*; +import java.util.function.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.MoveOp; + +/** + * Represents def-use tree of a constant. + */ +class DefUseTree { + private final LIRInstruction instruction; + private final AbstractBlock block; + private final List uses; + + public DefUseTree(LIRInstruction instruction, AbstractBlock block) { + assert instruction instanceof MoveOp : "Not a MoveOp: " + instruction; + this.instruction = instruction; + this.block = block; + this.uses = new ArrayList<>(); + } + + public Variable getVariable() { + return (Variable) ((MoveOp) instruction).getResult(); + } + + public Constant getConstant() { + return (Constant) ((MoveOp) instruction).getInput(); + } + + public LIRInstruction getInstruction() { + return instruction; + } + + public AbstractBlock getBlock() { + return block; + } + + @Override + public String toString() { + return "DefUseTree [" + instruction + "|" + block + "," + uses + "]"; + } + + public void addUsage(AbstractBlock b, LIRInstruction inst, ValuePosition position) { + uses.add(new UseEntry(b, inst, position)); + } + + public int usageCount() { + return uses.size(); + } + + public void forEach(Consumer action) { + uses.forEach(action); + } + +} \ No newline at end of file diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/UseEntry.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/UseEntry.java Thu Aug 28 17:49:37 2014 -0700 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014, 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.lir.constopt; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.lir.*; + +/** + * Represents a usage of a constant. + */ +class UseEntry { + + private final AbstractBlock block; + private final LIRInstruction instruction; + private final ValuePosition position; + + public UseEntry(AbstractBlock block, LIRInstruction instruction, ValuePosition position) { + this.block = block; + this.instruction = instruction; + this.position = position; + } + + public LIRInstruction getInstruction() { + return instruction; + } + + public AbstractBlock getBlock() { + return block; + } + + public ValuePosition getPosition() { + return position; + } + + public Value getValue() { + return position.get(instruction); + } + + @Override + public String toString() { + return "Use[" + getValue() + ":" + instruction + ":" + block + "]"; + } +} \ No newline at end of file diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/VariableMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/VariableMap.java Thu Aug 28 17:49:37 2014 -0700 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014, 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.lir.constopt; + +import java.util.*; +import java.util.function.*; + +import com.oracle.graal.lir.*; + +/** + * Maps variables to a generic type. + * + * TODO (je) evaluate data structure + */ +class VariableMap { + + private final ArrayList content; + + public VariableMap() { + content = new ArrayList<>(); + } + + public T get(Variable key) { + if (key == null || key.index >= content.size()) { + return null; + } + return content.get(key.index); + } + + public T put(Variable key, T value) { + assert key != null : "Key cannot be null"; + assert value != null : "Value cannot be null"; + while (key.index >= content.size()) { + content.add(null); + } + return content.set(key.index, value); + } + + public T remove(Variable key) { + assert key != null : "Key cannot be null"; + if (key.index >= content.size()) { + return null; + } + return content.set(key.index, null); + } + + public void forEach(Consumer action) { + for (T e : content) { + if (e != null) { + action.accept(e); + } + } + } + + /** + * Keeps only keys which match the given predicate. + */ + public void filter(Predicate predicate) { + for (int i = 0; i < content.size(); i++) { + T e = content.get(i); + if (e != null && !predicate.test(e)) { + content.set(i, null); + } + } + } + +} \ No newline at end of file diff -r c9c416d90a4e -r e4cfc9ea2bd3 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 Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeGenerator.java Thu Aug 28 17:49:37 2014 -0700 @@ -379,7 +379,7 @@ callArgs.format("%s%s", sep, v.getSimpleName()); sep = ", "; } - f.format(") { return new %s(%s); }", genClassName, callArgs); + f.format(") { return USE_GENERATED_NODES ? new %s(%s) : new %s(%s); }", genClassName, callArgs, node.getSimpleName(), callArgs); throw new ElementException(constructor, "Missing Node class factory method '%s'", f); } if (!create.getModifiers().containsAll(asList(PUBLIC, STATIC))) { diff -r c9c416d90a4e -r e4cfc9ea2bd3 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 Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeProcessor.java Thu Aug 28 17:49:37 2014 -0700 @@ -22,8 +22,11 @@ */ package com.oracle.graal.nodeinfo.processor; +import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; + import java.io.*; import java.util.*; +import java.util.stream.*; import javax.annotation.processing.*; import javax.lang.model.*; @@ -46,23 +49,39 @@ return SourceVersion.latest(); } + /** + * Node class currently being processed. + */ + private Element scope; + + public static boolean isEnclosedIn(Element e, Element scopeElement) { + List elementHierarchy = getElementHierarchy(e); + return elementHierarchy.contains(scopeElement); + } + void errorMessage(Element element, String format, Object... args) { message(Kind.ERROR, element, format, args); } void message(Kind kind, Element element, String format, Object... args) { - processingEnv.getMessager().printMessage(kind, String.format(format, args), element); + 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(".")); + processingEnv.getMessager().printMessage(kind, String.format(loc + ": " + format, args), scope); + } else { + processingEnv.getMessager().printMessage(kind, String.format(format, args), element); + } } /** * Bugs in an annotation processor can cause silent failure so try to report any exception * throws as errors. */ - private void reportException(Element element, Throwable t) { + private void reportException(Kind kind, Element element, Throwable t) { StringWriter buf = new StringWriter(); t.printStackTrace(new PrintWriter(buf)); buf.toString(); - errorMessage(element, "Exception thrown during processing: %s", buf.toString()); + message(kind, element, "Exception thrown during processing: %s", buf.toString()); } ProcessingEnvironment getProcessingEnv() { @@ -94,6 +113,7 @@ GraphNodeGenerator gen = new GraphNodeGenerator(this); for (Element element : roundEnv.getElementsAnnotatedWith(NodeInfo.class)) { + scope = element; try { if (!isNodeType(element)) { errorMessage(element, "%s can only be applied to Node subclasses", NodeInfo.class.getSimpleName()); @@ -126,11 +146,9 @@ } catch (ElementException ee) { errorMessage(ee.element, ee.getMessage()); } catch (Throwable t) { - if (!isBug367599(t)) { - reportException(element, t); - } else { - message(Kind.NOTE, element, t.toString()); - } + reportException(isBug367599(t) ? Kind.NOTE : Kind.ERROR, element, t); + } finally { + scope = null; } } return false; @@ -141,14 +159,16 @@ * href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599">Bug 367599. */ public static boolean isBug367599(Throwable t) { - for (StackTraceElement ste : t.getStackTrace()) { - if (ste.toString().contains("org.eclipse.jdt.internal.apt.pluggable.core.filer.IdeFilerImpl.create")) { - // See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599 - return true; + if (t instanceof FilerException) { + for (StackTraceElement ste : t.getStackTrace()) { + if (ste.toString().contains("org.eclipse.jdt.internal.apt.pluggable.core.filer.IdeFilerImpl.create")) { + // See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599 + return true; + } } - } - if (t.getCause() != null) { - return isBug367599(t.getCause()); + if (t.getCause() != null) { + return isBug367599(t.getCause()); + } } return false; } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -32,7 +32,7 @@ @NodeInfo public abstract class AbstractFixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, GuardingNode { - @Input(InputType.Condition) LogicNode condition; + @Input(InputType.Condition) protected LogicNode condition; private final DeoptimizationReason reason; private final DeoptimizationAction action; private boolean negated; diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -42,10 +42,6 @@ return USE_GENERATED_NODES ? new BeginNodeGen() : new BeginNode(); } - public static Class getGenClass() { - return USE_GENERATED_NODES ? BeginNodeGen.class : BeginNode.class; - } - protected BeginNode() { super(StampFactory.forVoid()); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -30,10 +30,6 @@ return USE_GENERATED_NODES ? new EndNodeGen() : new EndNode(); } - public static Class getGenClass() { - return USE_GENERATED_NODES ? EndNodeGen.class : EndNode.class; - } - EndNode() { } } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -30,7 +30,7 @@ @NodeInfo public abstract class FloatingAnchoredNode extends FloatingNode { - @Input(InputType.Anchor) AnchoringNode anchor; + @Input(InputType.Anchor) protected AnchoringNode anchor; public FloatingAnchoredNode(Stamp stamp) { super(stamp); diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -44,7 +44,7 @@ @NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}", allowedUsageTypes = {InputType.Guard}) public class GuardNode extends FloatingAnchoredNode implements Canonicalizable, IterableNodeType, GuardingNode { - @Input(InputType.Condition) LogicNode condition; + @Input(InputType.Condition) protected LogicNode condition; private final DeoptimizationReason reason; private Constant speculation; private DeoptimizationAction action; diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -220,7 +220,7 @@ do { BeginNode trueSucc = trueSuccessor(); BeginNode falseSucc = falseSuccessor(); - if (trueSucc.getClass() == BeginNode.getGenClass() && falseSucc.getClass() == BeginNode.getGenClass() && trueSucc.next() instanceof FixedWithNextNode && + if (trueSucc.getNodeClass().is(BeginNode.class) && falseSucc.getNodeClass().is(BeginNode.class) && trueSucc.next() instanceof FixedWithNextNode && falseSucc.next() instanceof FixedWithNextNode) { FixedWithNextNode trueNext = (FixedWithNextNode) trueSucc.next(); FixedWithNextNode falseNext = (FixedWithNextNode) falseSucc.next(); diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -37,7 +37,7 @@ * The {@code InvokeNode} represents all kinds of method calls. */ @NodeInfo(nameTemplate = "Invoke#{p#targetMethod/s}", allowedUsageTypes = {InputType.Memory}) -public class InvokeNode extends AbstractMemoryCheckpoint implements Invoke, LIRLowerable, MemoryCheckpoint.Single, IterableNodeType { +public class InvokeNode extends AbstractMemoryCheckpoint implements Invoke, LIRLowerable, MemoryCheckpoint.Single { @Input(InputType.Extension) CallTargetNode callTarget; @OptionalInput(InputType.State) FrameState stateDuring; diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -43,14 +43,10 @@ return USE_GENERATED_NODES ? new MergeNodeGen() : new MergeNode(); } - public static Class getGenClass() { - return USE_GENERATED_NODES ? MergeNodeGen.class : MergeNode.class; + protected MergeNode() { } - MergeNode() { - } - - @Input(InputType.Association) NodeInputList ends = new NodeInputList<>(this); + @Input(InputType.Association) protected NodeInputList ends = new NodeInputList<>(this); @Override public void generate(NodeLIRBuilderTool gen) { diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -39,7 +39,7 @@ @NodeInfo public abstract class PhiNode extends FloatingNode implements Simplifiable { - @Input(InputType.Association) MergeNode merge; + @Input(InputType.Association) protected MergeNode merge; protected PhiNode(Stamp stamp, MergeNode merge) { super(stamp); diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -33,7 +33,7 @@ @NodeInfo(nameTemplate = "ValuePhi({i#values})") public class ValuePhiNode extends PhiNode { - @Input NodeInputList values; + @Input protected NodeInputList values; /** * Create a value phi with the specified stamp. diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -39,10 +39,6 @@ return USE_GENERATED_NODES ? new AndNodeGen(x, y) : new AndNode(x, y); } - public static Class getGenClass() { - return USE_GENERATED_NODES ? AndNodeGen.class : AndNode.class; - } - AndNode(ValueNode x, ValueNode y) { super(StampTool.and(x.stamp(), y.stamp()), x, y); assert x.stamp().isCompatible(y.stamp()); diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -37,10 +37,6 @@ return USE_GENERATED_NODES ? new FloatAddNodeGen(x, y, isStrictFP) : new FloatAddNode(x, y, isStrictFP); } - public static Class getGenClass() { - return USE_GENERATED_NODES ? FloatAddNodeGen.class : FloatAddNode.class; - } - protected FloatAddNode(ValueNode x, ValueNode y, boolean isStrictFP) { super(x.stamp().unrestricted(), x, y, isStrictFP); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -37,10 +37,6 @@ return USE_GENERATED_NODES ? new FloatMulNodeGen(x, y, isStrictFP) : new FloatMulNode(x, y, isStrictFP); } - public static Class getGenClass() { - return USE_GENERATED_NODES ? FloatMulNodeGen.class : FloatMulNode.class; - } - protected FloatMulNode(ValueNode x, ValueNode y, boolean isStrictFP) { super(x.stamp().unrestricted(), x, y, isStrictFP); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -38,10 +38,6 @@ return USE_GENERATED_NODES ? new FloatSubNodeGen(x, y, isStrictFP) : new FloatSubNode(x, y, isStrictFP); } - public static Class getGenClass() { - return USE_GENERATED_NODES ? FloatSubNodeGen.class : FloatSubNode.class; - } - protected FloatSubNode(ValueNode x, ValueNode y, boolean isStrictFP) { super(x.stamp().unrestricted(), x, y, isStrictFP); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -38,10 +38,6 @@ return USE_GENERATED_NODES ? new IntegerAddNodeGen(x, y) : new IntegerAddNode(x, y); } - public static Class getGenClass() { - return USE_GENERATED_NODES ? IntegerAddNodeGen.class : IntegerAddNode.class; - } - protected IntegerAddNode(ValueNode x, ValueNode y) { super(StampTool.add(x.stamp(), y.stamp()), x, y); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -97,7 +97,7 @@ } if (next() instanceof IntegerDivNode) { - NodeClass nodeClass = NodeClass.get(this.getClass()); + NodeClass nodeClass = getNodeClass(); if (next().getClass() == this.getClass() && nodeClass.inputsEqual(this, next()) && nodeClass.valueEqual(this, next())) { return next(); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -38,10 +38,6 @@ return USE_GENERATED_NODES ? new IntegerMulNodeGen(x, y) : new IntegerMulNode(x, y); } - public static Class getGenClass() { - return USE_GENERATED_NODES ? IntegerMulNodeGen.class : IntegerMulNode.class; - } - protected IntegerMulNode(ValueNode x, ValueNode y) { super(x.stamp().unrestricted(), x, y); assert x.stamp().isCompatible(y.stamp()); diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -39,10 +39,6 @@ return USE_GENERATED_NODES ? new IntegerSubNodeGen(x, y) : new IntegerSubNode(x, y); } - public static Class getGenClass() { - return USE_GENERATED_NODES ? IntegerSubNodeGen.class : IntegerSubNode.class; - } - protected IntegerSubNode(ValueNode x, ValueNode y) { super(StampTool.sub(x.stamp(), y.stamp()), x, y); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -39,10 +39,6 @@ return USE_GENERATED_NODES ? new OrNodeGen(x, y) : new OrNode(x, y); } - public static Class getGenClass() { - return USE_GENERATED_NODES ? OrNodeGen.class : OrNode.class; - } - OrNode(ValueNode x, ValueNode y) { super(StampTool.or(x.stamp(), y.stamp()), x, y); assert x.stamp().isCompatible(y.stamp()); diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -39,10 +39,6 @@ return USE_GENERATED_NODES ? new XorNodeGen(x, y) : new XorNode(x, y); } - public static Class getGenClass() { - return USE_GENERATED_NODES ? XorNodeGen.class : XorNode.class; - } - protected XorNode(ValueNode x, ValueNode y) { super(StampTool.xor(x.stamp(), y.stamp()), x, y); assert x.stamp().isCompatible(y.stamp()); diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -34,7 +34,7 @@ @NodeInfo public class AbstractNewArrayNode extends AbstractNewObjectNode implements ArrayLengthProvider { - @Input ValueNode length; + @Input protected ValueNode length; @Override public ValueNode length() { diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -42,7 +42,7 @@ return USE_GENERATED_NODES ? new MonitorIdNodeGen(lockDepth) : new MonitorIdNode(lockDepth); } - MonitorIdNode(int lockDepth) { + protected MonitorIdNode(int lockDepth) { super(StampFactory.forVoid()); this.lockDepth = lockDepth; } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -51,7 +51,7 @@ return USE_GENERATED_NODES ? new NewArrayNodeGen(elementType, length, fillContents) : new NewArrayNode(elementType, length, fillContents); } - NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents) { + protected NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents) { super(StampFactory.exactNonNull(elementType.getArrayClass()), length, fillContents); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java Thu Aug 28 17:49:37 2014 -0700 @@ -116,7 +116,7 @@ parent = loops.get(null); break; } else { - assert current.getClass() == MergeNode.getGenClass() : current; + assert current.getNodeClass().is(MergeNode.class) : current; // follow any path upwards - it doesn't matter which one current = ((MergeNode) current).forwardEndAt(0); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyNoNodeClassLiteralIdentityTests.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyNoNodeClassLiteralIdentityTests.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyNoNodeClassLiteralIdentityTests.java Thu Aug 28 17:49:37 2014 -0700 @@ -38,8 +38,8 @@ * Since only {@linkplain GeneratedNode generated} {@link Node} types can be instantiated (which is * checked by an assertion in {@link Node#Node()}), any identity test of a node's * {@linkplain Object#getClass() class} against a class literal of a non-generated node types will - * always return false. Instead, a static {@code getGenClass()} helper method should be used for - * such identity tests. For example, instead of: + * always return false. Instead, the {@link NodeClass#is(Class)} method should be used. For example, + * instead of: * *

  *     if (operation.getClass() == IntegerAddNode.class) { ... }
@@ -48,7 +48,7 @@
  * this should be used:
  *
  * 
- *     if (operation.getClass() == IntegerAddNode.getGenClass()) { ... }
+ *     if (operation.getNodeClass().is(IntegerAddNode.class)) { ... }
  * 
* * This phase verifies there are no identity tests against class literals for non-generated Node @@ -60,8 +60,10 @@ protected boolean verify(StructuredGraph graph, PhaseContext context) { Map errors = new HashMap<>(); + MetaAccessProvider metaAccess = context.getMetaAccess(); + ResolvedJavaType nodeClassType = metaAccess.lookupJavaType(Node.class); + for (ConstantNode c : ConstantNode.getConstantNodes(graph)) { - ResolvedJavaType nodeClassType = context.getMetaAccess().lookupJavaType(Node.class); ResolvedJavaType nodeType = context.getConstantReflection().asJavaType(c.asConstant()); if (nodeType != null && nodeClassType.isAssignableFrom(nodeType)) { NodeIterable usages = c.usages(); @@ -69,10 +71,7 @@ if (!(n instanceof ObjectEqualsNode)) { continue; } - String loc = GraphUtil.approxSourceLocation(n); - if (loc == null) { - loc = graph.method().asStackTraceElement(0).toString() + " " + n; - } + String loc = getLocation(n, graph); errors.put(nodeType.toJavaName(false), loc); } } @@ -92,4 +91,15 @@ } throw new VerificationError(f.toString()); } + + private static String getLocation(Node node, StructuredGraph graph) { + String loc = GraphUtil.approxSourceLocation(node); + StackTraceElement ste = graph.method().asStackTraceElement(0); + if (loc == null) { + loc = ste.toString(); + } else { + loc = ste.getClassName() + "." + ste.getMethodName() + "(" + loc + ")"; + } + return loc; + } } diff -r c9c416d90a4e -r e4cfc9ea2bd3 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 Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Thu Aug 28 17:49:37 2014 -0700 @@ -273,24 +273,20 @@ } } - // Currently no node printing for lir - if (lir == null) { - Node cur = block.getBeginNode(); - while (true) { - printNode(cur, false); + Node cur = block.getBeginNode(); + while (true) { + printNode(cur, false); - if (cur == block.getEndNode()) { - for (Map.Entry entry : latestScheduling.entries()) { - if (entry.getValue() == block && !inFixedSchedule(entry.getKey()) && !printedNodes.isMarked(entry.getKey())) { - printNode(entry.getKey(), true); - } + if (cur == block.getEndNode()) { + for (Map.Entry entry : latestScheduling.entries()) { + if (entry.getValue() == block && !inFixedSchedule(entry.getKey()) && !printedNodes.isMarked(entry.getKey())) { + printNode(entry.getKey(), true); } - break; } - assert cur.successors().count() == 1; - cur = cur.successors().first(); + break; } - + assert cur.successors().count() == 1; + cur = cur.successors().first(); } out.enableIndentation(); diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Thu Aug 28 17:49:37 2014 -0700 @@ -50,7 +50,6 @@ private JavaMethod curMethod; private List curDecorators = Collections.emptyList(); private final boolean dumpFrontend; - private Object previousObject; public CFGPrinterObserver(boolean dumpFrontend) { this.dumpFrontend = dumpFrontend; @@ -162,10 +161,8 @@ } } else if (object instanceof LIR) { - // No need to print the HIR nodes again if this is not the first - // time dumping the same LIR since the HIR will not have changed. - boolean printNodes = previousObject != object && cfgPrinter.cfg != null; - cfgPrinter.printCFG(message, cfgPrinter.lir.codeEmittingOrder(), printNodes); + // Currently no node printing for lir + cfgPrinter.printCFG(message, cfgPrinter.lir.codeEmittingOrder(), false); } else if (object instanceof SchedulePhase) { cfgPrinter.printSchedule(message, (SchedulePhase) object); @@ -193,7 +190,6 @@ cfgPrinter.cfg = null; cfgPrinter.flush(); - previousObject = object; } private static boolean isCompilationResultAndInstalledCode(Object object) { diff -r c9c416d90a4e -r e4cfc9ea2bd3 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 Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Thu Aug 28 17:49:37 2014 -0700 @@ -174,9 +174,9 @@ printProperty(bit, "true"); } } - if (node.getClass() == BeginNode.getGenClass()) { + if (node.getNodeClass().is(BeginNode.class)) { printProperty("shortName", "B"); - } else if (node.getClass() == EndNode.getGenClass()) { + } else if (node.getNodeClass().is(EndNode.class)) { printProperty("shortName", "E"); } if (node.predecessor() != null) { diff -r c9c416d90a4e -r e4cfc9ea2bd3 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 Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Thu Aug 28 17:49:37 2014 -0700 @@ -81,6 +81,7 @@ private final ResolvedJavaMethod[] callNodeMethod; private final ResolvedJavaMethod[] callTargetMethod; private final ResolvedJavaMethod[] anyFrameMethod; + private final Map callTargets = Collections.synchronizedMap(new WeakHashMap()); private HotSpotTruffleRuntime() { installOptimizedCallTargetCallMethod(); @@ -115,7 +116,10 @@ } else { compilationPolicy = new InterpreterOnlyCompilationPolicy(); } - return new OptimizedCallTarget(rootNode, this, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue(), compilationPolicy, new HotSpotSpeculationLog()); + OptimizedCallTarget target = new OptimizedCallTarget(rootNode, this, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue(), compilationPolicy, + new HotSpotSpeculationLog()); + callTargets.put(target, null); + return target; } public LoopNode createLoopNode(RepeatingNode repeating) { @@ -361,6 +365,11 @@ installOptimizedCallTargetCallMethod(); } + @Override + public List getCallTargets() { + return new ArrayList<>(callTargets.keySet()); + } + public void notifyTransferToInterpreter() { CompilerAsserts.neverPartOfCompilation(); if (TraceTruffleTransferToInterpreter.getValue()) { diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Thu Aug 28 17:49:37 2014 -0700 @@ -333,6 +333,9 @@ public final Object callInlined(Object[] arguments) { if (CompilerDirectives.inInterpreter()) { compilationProfile.reportInlinedCall(); + if (isValid()) { + return callDirect(arguments); + } } VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), arguments); return callProxy(frame); diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedLoopNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedLoopNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedLoopNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -23,7 +23,6 @@ package 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.*; @@ -33,36 +32,24 @@ */ public final class OptimizedLoopNode extends LoopNode { - @CompilationFinal private int loopCount; - public OptimizedLoopNode(RepeatingNode body) { super(body); } @Override public void executeLoop(VirtualFrame frame) { + int loopCount = 0; try { - do { - } while (executeBody(frame)); + while (executeRepeatingNode(frame)) { + if (CompilerDirectives.inInterpreter()) { + loopCount++; + } + } } finally { - loopDone(); + if (CompilerDirectives.inInterpreter()) { + getRootNode().reportLoopCount(loopCount); + } } } - private final boolean executeBody(VirtualFrame frame) { - boolean result = executeRepeatNode(frame); - if (CompilerDirectives.inInterpreter()) { - if (result) { - loopCount++; - } - } - return result; - } - - private void loopDone() { - if (CompilerDirectives.inInterpreter()) { - getRootNode().reportLoopCount(loopCount); - loopCount = 0; - } - } -} \ No newline at end of file +} diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.nfi.test/test/com/oracle/nfi/test/NativeFunctionInterfaceTest.java --- a/graal/com.oracle.nfi.test/test/com/oracle/nfi/test/NativeFunctionInterfaceTest.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.nfi.test/test/com/oracle/nfi/test/NativeFunctionInterfaceTest.java Thu Aug 28 17:49:37 2014 -0700 @@ -347,46 +347,50 @@ @Test public void test15() { assumeTrue(nfi.isDefaultLibrarySearchSupported()); - try { - nfi.getFunctionHandle("an invalid function name", int.class); + NativeFunctionHandle functionHandle = nfi.getFunctionHandle("an invalid function name", int.class); + if (functionHandle != null) { fail(); - } catch (UnsatisfiedLinkError e) { } } @Test public void test16() { NativeLibraryHandle javaLib = nfi.getLibraryHandle(getJavaLibPath()); - try { - - nfi.getFunctionHandle(javaLib, "an invalid function name", int.class); + NativeFunctionHandle functionHandle = nfi.getFunctionHandle(javaLib, "an invalid function name", int.class); + if (functionHandle != null) { fail(); - } catch (UnsatisfiedLinkError e) { } } @Test public void test17() { NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())}; - try { - nfi.getFunctionPointer(libs, "an invalid function name"); + NativeFunctionHandle functionHandle = nfi.getFunctionHandle(libs, "an invalid function name", int.class); + if (functionHandle != null) { fail(); - } catch (UnsatisfiedLinkError e) { } } @Test public void test18() { NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())}; - try { - nfi.getFunctionHandle(libs, "an invalid function name", int.class); + NativeFunctionHandle functionHandle = nfi.getFunctionHandle(libs, "an invalid function name", int.class); + if (functionHandle != null) { fail(); - } catch (UnsatisfiedLinkError e) { } } @Test public void test19() { + NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())}; + NativeFunctionPointer functionPointer = nfi.getFunctionPointer(libs, "an invalid function name"); + if (functionPointer != null) { + fail(); + } + } + + @Test + public void test20() { try { nfi.getLibraryHandle("an invalid library name"); fail(); diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionInterface.java --- a/graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionInterface.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionInterface.java Thu Aug 28 17:49:37 2014 -0700 @@ -51,8 +51,8 @@ * * @param libraries the ordered list of libraries to search for the function * @param name the name of the function to be resolved - * @return a pointer to the native function - * @throws UnsatisfiedLinkError if the function could not be resolved + * @return a pointer to the native function, or null if the function pointer could + * not be resolved */ NativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraries, String name); @@ -65,8 +65,8 @@ * @param name the name of the function to be resolved * @param returnType the type of the return value * @param argumentTypes the types of the arguments - * @return the function handle of the native function - * @throws UnsatisfiedLinkError if the function handle could not be resolved + * @return the function handle of the native function, or null if the function + * handle could not be resolved */ NativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class returnType, Class... argumentTypes); @@ -78,8 +78,8 @@ * @param functionPointer a function pointer * @param returnType the type of the return value * @param argumentTypes the types of the arguments - * @return the function handle of the native function - * @throws UnsatisfiedLinkError the function handle could not be created + * @return the function handle of the native function, or null if the function + * handle could not be resolved */ NativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes); @@ -92,8 +92,8 @@ * @param name the name of the function to be resolved * @param returnType the type of the return value * @param argumentTypes the types of the arguments - * @return the function handle of the native function - * @throws UnsatisfiedLinkError if the function handle could not be created + * @return the function handle of the native function, or null if the function + * handle could not be resolved */ NativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class returnType, Class... argumentTypes); @@ -105,10 +105,9 @@ * @param name the name of the function to be resolved * @param returnType the type of the return value * @param argumentTypes the types of the arguments - * @return the function handle of the native function - * @throws UnsatisfiedLinkError if default library searching is not - * {@linkplain #isDefaultLibrarySearchSupported() supported} or if the function - * could not be resolved + * @return the function handle of the native function, or null if default library + * searching is not {@linkplain #isDefaultLibrarySearchSupported() supported} or if the + * function could not be resolved */ NativeFunctionHandle getFunctionHandle(String name, Class returnType, Class... argumentTypes); diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java Thu Aug 28 17:49:37 2014 -0700 @@ -26,12 +26,16 @@ import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; +import org.junit.*; import org.junit.experimental.theories.*; import org.junit.runner.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.dsl.test.SourceSectionTestFactory.SourceSection0Factory; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.*; +import com.oracle.truffle.api.dsl.test.SourceSectionTestFactory.SourceSection1Factory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; @@ -54,7 +58,7 @@ expectSourceSection(root.getNode(), section); } - private void expectSourceSection(Node root, SourceSection section) { + private static void expectSourceSection(Node root, SourceSection section) { assertThat(root.getSourceSection(), is(sameInstance(section))); for (Node child : root.getChildren()) { if (child instanceof ArgumentNode) { @@ -101,4 +105,33 @@ return a; // the generic answer to all questions } } + + @Test + public void testCreateCast() { + SourceSection section = new NullSourceSection("a", "b"); + TestRootNode root = createRootPrefix(SourceSection1Factory.getInstance(), true, section); + expectSourceSection(root.getNode(), section); + assertThat((int) executeWith(root, 1), is(1)); + expectSourceSection(root.getNode(), section); + } + + @NodeChild("a") + static class SourceSection1 extends ValueNode { + + public SourceSection1(SourceSection section) { + super(section); + } + + @CreateCast("a") + public ValueNode cast(ValueNode node) { + assert getSourceSection() != null; + return node; + } + + @Specialization + int do0(int a) { + return a; + } + + } } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Thu Aug 28 17:49:37 2014 -0700 @@ -24,7 +24,6 @@ import static org.junit.Assert.*; -import java.lang.reflect.*; import java.util.*; import com.oracle.truffle.api.*; @@ -47,41 +46,32 @@ return nodes; } - static E createNode(NodeFactory factory, Object... constants) { + static E createNode(NodeFactory factory, boolean prefixConstants, Object... constants) { ArgumentNode[] argumentNodes = arguments(factory.getExecutionSignature().size()); List argumentList = new ArrayList<>(); + if (prefixConstants) { + argumentList.addAll(Arrays.asList(constants)); + } if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass())) { argumentList.add(argumentNodes); } else { argumentList.addAll(Arrays.asList(argumentNodes)); } - argumentList.addAll(Arrays.asList(constants)); + if (!prefixConstants) { + argumentList.addAll(Arrays.asList(constants)); + } return factory.createNode(argumentList.toArray(new Object[argumentList.size()])); } - static E createGenericNode(NodeFactory factory, Object... constants) { - Method createGenericMethod; - try { - createGenericMethod = factory.getClass().getMethod("createGeneric", factory.getNodeClass()); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - try { - return factory.getNodeClass().cast(createGenericMethod.invoke(null, createNode(factory, constants))); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - static TestRootNode createRoot(NodeFactory factory, Object... constants) { - TestRootNode rootNode = new TestRootNode<>(createNode(factory, constants)); + TestRootNode rootNode = new TestRootNode<>(createNode(factory, false, constants)); rootNode.adoptChildren(); return rootNode; } - static TestRootNode createGenericRoot(NodeFactory factory, Object... constants) { - TestRootNode rootNode = new TestRootNode<>(createGenericNode(factory, constants)); + static TestRootNode createRootPrefix(NodeFactory factory, boolean prefixConstants, Object... constants) { + TestRootNode rootNode = new TestRootNode<>(createNode(factory, prefixConstants, constants)); rootNode.adoptChildren(); return rootNode; } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java Thu Aug 28 17:49:37 2014 -0700 @@ -28,6 +28,7 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; public class TypeSystemTest { @@ -69,6 +70,10 @@ super(null); } + public ValueNode(SourceSection sourceSection) { + super(sourceSection); + } + public int executeInt(VirtualFrame frame) throws UnexpectedResultException { return SimpleTypesGen.SIMPLETYPES.expectInteger(execute(frame)); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java Thu Aug 28 17:49:37 2014 -0700 @@ -22,13 +22,20 @@ */ package com.oracle.truffle.api.test; +import static org.junit.Assert.*; + +import java.util.*; + import org.junit.*; import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; /** *

Accessing the Truffle Runtime

- * + * *

* The Truffle runtime can be accessed at any point in time globally using the static method * {@link Truffle#getRuntime()}. This method is guaranteed to return a non-null Truffle runtime @@ -36,7 +43,7 @@ * default implementation of the {@link TruffleRuntime} interface with its own implementation for * providing improved performance. *

- * + * *

* The next part of the Truffle API introduction is at * {@link com.oracle.truffle.api.test.RootNodeTest}. @@ -44,10 +51,104 @@ */ public class TruffleRuntimeTest { + private TruffleRuntime runtime; + + @Before + public void setup() { + this.runtime = Truffle.getRuntime(); + } + + private static RootNode createTestRootNode() { + return new RootNode() { + @Override + public Object execute(VirtualFrame frame) { + return 42; + } + }; + } + @Test public void test() { - TruffleRuntime runtime = Truffle.getRuntime(); - Assert.assertNotNull(runtime); - Assert.assertNotNull(runtime.getName()); + assertNotNull(runtime); + assertNotNull(runtime.getName()); + } + + @Test + public void testCreateCallTarget() { + RootNode rootNode = createTestRootNode(); + RootCallTarget target = runtime.createCallTarget(rootNode); + assertNotNull(target); + assertEquals(target.call(), 42); + assertSame(rootNode, target.getRootNode()); + } + + @Test + public void testGetCallTargets1() { + RootNode rootNode = createTestRootNode(); + RootCallTarget target = runtime.createCallTarget(rootNode); + assertTrue(runtime.getCallTargets().indexOf(target) != -1); + } + + @Test + public void testGetCallTargets2() { + RootNode rootNode = createTestRootNode(); + RootCallTarget target1 = runtime.createCallTarget(rootNode); + RootCallTarget target2 = runtime.createCallTarget(rootNode); + assertTrue(runtime.getCallTargets().indexOf(target1) != -1); + assertTrue(runtime.getCallTargets().indexOf(target2) != -1); + } + + /* + * This test case documents the use case for profilers and debuggers where they need to access + * multiple call targets for the same source section. This case may happen when the optimization + * system decides to duplicate call targets to achieve better performance. + */ + @Test + public void testGetCallTargets3() { + Source source1 = Source.fromText("a\nb\n", ""); + SourceSection sourceSection1 = source1.createSection("foo", 1); + SourceSection sourceSection2 = source1.createSection("bar", 2); + + RootNode rootNode1 = createTestRootNode(); + rootNode1.assignSourceSection(sourceSection1); + RootNode rootNode2 = createTestRootNode(); + rootNode2.assignSourceSection(sourceSection2); + RootNode rootNode2Copy = NodeUtil.cloneNode(rootNode2); + + assertSame(rootNode2.getSourceSection(), rootNode2Copy.getSourceSection()); + + RootCallTarget target1 = runtime.createCallTarget(rootNode1); + RootCallTarget target2 = runtime.createCallTarget(rootNode2); + RootCallTarget target2Copy = runtime.createCallTarget(rootNode2Copy); + + Map> groupedTargets = groupUniqueCallTargets(); + + List targets1 = groupedTargets.get(sourceSection1); + assertEquals(1, targets1.size()); + assertEquals(target1, targets1.get(0)); + + List targets2 = groupedTargets.get(sourceSection2); + assertEquals(2, targets2.size()); + // order of targets2 is not guaranteed + assertTrue(target2 == targets2.get(0) ^ target2Copy == targets2.get(0)); + assertTrue(target2 == targets2.get(1) ^ target2Copy == targets2.get(1)); + } + + private static Map> groupUniqueCallTargets() { + Map> groupedTargets = new HashMap<>(); + for (RootCallTarget target : Truffle.getRuntime().getCallTargets()) { + SourceSection section = target.getRootNode().getSourceSection(); + if (section == null) { + // can not identify root node to a unique call target. Print warning? + continue; + } + List targets = groupedTargets.get(section); + if (targets == null) { + targets = new ArrayList<>(); + groupedTargets.put(section, targets); + } + targets.add(target); + } + return groupedTargets; } } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Thu Aug 28 17:49:37 2014 -0700 @@ -24,6 +24,8 @@ */ package com.oracle.truffle.api; +import java.util.*; + import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; @@ -137,6 +139,12 @@ FrameInstance getCurrentFrame(); /** + * Returns a list of all still referenced {@link RootCallTarget} instances that were created + * using {@link #createCallTarget(RootNode)}. + */ + List getCallTargets(); + + /** * Internal API method. Do not use. */ void notifyTransferToInterpreter(); diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultLoopNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultLoopNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultLoopNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -35,7 +35,7 @@ @Override public void executeLoop(VirtualFrame frame) { - do { - } while (executeRepeatNode(frame)); + while (executeRepeatingNode(frame)) { + } } } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Thu Aug 28 17:49:37 2014 -0700 @@ -41,6 +41,7 @@ private ThreadLocal> stackTraces = new ThreadLocal<>(); private ThreadLocal currentFrames = new ThreadLocal<>(); + private final Map callTargets = Collections.synchronizedMap(new WeakHashMap()); public DefaultTruffleRuntime() { if (Truffle.getRuntime() != null) { @@ -55,7 +56,9 @@ @Override public RootCallTarget createCallTarget(RootNode rootNode) { - return new DefaultCallTarget(rootNode, this); + DefaultCallTarget target = new DefaultCallTarget(rootNode, this); + callTargets.put(target, null); + return target; } public DirectCallNode createDirectCallNode(CallTarget target) { @@ -132,6 +135,11 @@ } @Override + public List getCallTargets() { + return new ArrayList<>(callTargets.keySet()); + } + + @Override public FrameInstance getCurrentFrame() { return currentFrames.get(); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentable.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentable.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentable.java Thu Aug 28 17:49:37 2014 -0700 @@ -24,25 +24,20 @@ */ package com.oracle.truffle.api.instrument; -import com.oracle.truffle.api.*; - +/** + * Any Truffle node implementing this interface can be "instrumented" by installing a {@link Probe} + * that intercepts {@link ExecutionEvents} at the node and routes them to any {@link Instrument}s + * that have been attached to the {@link Probe}. Only one {@link Probe} may be installed at each + * node; subsequent calls return the one already installed. + */ public interface Instrumentable { /** - * Optionally applies instrumentation at a Truffle AST node, depending on guest - * language characteristics and use-case policy. Ideally, the parent node of the guest language - * implements this interface. - *

    - *
  • if no instrumentation is to be applied, returns the AST node unmodified;
  • - *
  • if an AST node is to be instrumented, then creates a new Wrapper that decorates - * the AST node. Additionally, this creates a probe on the wrapper that is to be used for - * attaching instruments. This {@link Probe} is notified of all {@link ExecutionEvents} at the - * wrapped AST node.
  • - *
+ * Enables "instrumentation" of this Truffle node by tools, where this node is presumed to be + * part (and not the root of) of a well-formed Truffle AST that is not being executed. The AST + * may be modified. * - * @param context The {@link ExecutionContext} of the guest language used to create probes on - * the wrapper. * @return The probe that was created. */ - public Probe probe(ExecutionContext context); + Probe probe(); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java Thu Aug 28 17:49:37 2014 -0700 @@ -37,6 +37,7 @@ */ public interface Visualizer { + // TODO (mlvdv) "Visualizer" is misleading: rename. /** * Gets a printer for Truffle ASTs, possibly specialized to be helpful for a specific guest * language implementation. diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -343,18 +343,18 @@ * {@link Node#getSourceSection()}, which is {@code null} for all instances of * {@link InstrumentationNode} since they have no corresponding source of their own. */ - private final SourceSection source; + private final SourceSection probedSourceSection; /** * Constructor. * - * @param source The {@link SourceSection} associated with this probe. + * @param probedSourceSection The {@link SourceSection} associated with this probe. * @param probeCallback The {@link ProbeCallback} to inform when tags have been added to * this probe. */ - private ProbeImpl(SourceSection source, ProbeCallback probeCallback) { + private ProbeImpl(SourceSection probedSourceSection, ProbeCallback probeCallback) { this.probeCallback = probeCallback; - this.source = source; + this.probedSourceSection = probedSourceSection; this.probeUnchanged = Truffle.getRuntime().createAssumption(); this.next = null; } @@ -363,7 +363,7 @@ * Returns the {@link SourceSection} associated with this probe. */ public SourceSection getSourceLocation() { - return source; + return probedSourceSection; } /** diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToProbeCollectionMap.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToProbeCollectionMap.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToProbeCollectionMap.java Thu Aug 28 17:49:37 2014 -0700 @@ -24,6 +24,7 @@ */ package com.oracle.truffle.api.instrument.impl; +import java.io.*; import java.util.*; import com.oracle.truffle.api.instrument.*; @@ -35,6 +36,9 @@ */ public class LineLocationToProbeCollectionMap implements ProbeListener { + private static final boolean TRACE = false; + private static final PrintStream OUT = System.out; + /** * Map: Source line ==> probes associated with source sections starting on the line. */ @@ -44,8 +48,13 @@ } public void newProbeInserted(SourceSection source, Probe probe) { - if (source != null && !(source instanceof NullSourceSection)) - this.addProbeToLine(source.getLineLocation(), probe); + if (source != null && !(source instanceof NullSourceSection)) { + final LineLocation lineLocation = source.getLineLocation(); + if (TRACE) { + OUT.println("LineLocationToProbeCollectionMap: adding " + lineLocation + " Probe=" + probe); + } + this.addProbeToLine(lineLocation, probe); + } } public void probeTaggedAs(Probe probe, SyntaxTag tag) { @@ -98,9 +107,9 @@ } /** - * + * * Returns a collection of {@link Probe}s whose associated source begins at the given - * {@link LineLocation}. If there are no probes at that line, an empty list is returned. + * {@link LineLocation}, an empty list if none. * * @param line The line to check. * @return A collection of probes at the given line. @@ -108,24 +117,28 @@ public Collection getProbesAtLine(LineLocation line) { Collection probeList = lineToProbesMap.get(line); - if (probeList == null) - probeList = new ArrayList<>(1); - + if (probeList == null) { + return Collections.emptyList(); + } return probeList; } /** * Convenience method to get probes according to a int line number. Returns a collection of - * {@link Probe}s at the given line number. If there are no probes at that line, a new empty - * list is returned. + * {@link Probe}s at the given line number, an empty list if none. * * @param lineNumber The line number to check. - * @return A iterable collection of probes at the given line. + * @return A collection of probes at the given line. */ public Collection getProbesAtLineNumber(int lineNumber) { - ArrayList probes = new ArrayList<>(); - for (LineLocation line : lineToProbesMap.keySet()) { + final Set keySet = lineToProbesMap.keySet(); + if (keySet.size() == 0) { + return Collections.emptyList(); + } + + ArrayList probes = new ArrayList<>(); + for (LineLocation line : keySet) { if (line.getLineNumber() == lineNumber) probes.addAll(lineToProbesMap.get(line)); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToSourceSectionCollectionMap.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToSourceSectionCollectionMap.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToSourceSectionCollectionMap.java Thu Aug 28 17:49:37 2014 -0700 @@ -24,6 +24,7 @@ */ package com.oracle.truffle.api.instrument.impl; +import java.io.*; import java.util.*; import com.oracle.truffle.api.instrument.*; @@ -37,18 +38,24 @@ */ public class LineLocationToSourceSectionCollectionMap implements ProbeListener { + private static final boolean TRACE = false; + private static final PrintStream OUT = System.out; + /** * Map: Source line ==> source sections that exist on the line. */ private final Map> lineToSourceSectionsMap = new HashMap<>(); public LineLocationToSourceSectionCollectionMap() { - } public void newProbeInserted(SourceSection sourceSection, Probe probe) { if (sourceSection != null && !(sourceSection instanceof NullSourceSection)) { - this.addSourceSectionToLine(sourceSection.getLineLocation(), sourceSection); + final LineLocation lineLocation = sourceSection.getLineLocation(); + if (TRACE) { + OUT.println("LineLocationToSourceSectionCollectionMap: adding " + lineLocation + " Probe=" + probe); + } + this.addSourceSectionToLine(lineLocation, sourceSection); } } @@ -82,33 +89,38 @@ } /** - * Returns a collection of {@link SourceSection}s at the given {@link LineLocation}. If there - * are no source sections at that line, a new empty list of size 1 is returned. + * Returns a collection of {@link SourceSection}s at the given {@link LineLocation}, an empty + * list if none. * * @param line The line to check. - * @return A iterable collection of source sections at the given line. + * @return the source sections at the given line. */ public Collection getSourceSectionsAtLine(LineLocation line) { Collection sourceSectionList = lineToSourceSectionsMap.get(line); - if (sourceSectionList == null) - sourceSectionList = new ArrayList<>(1); - + if (sourceSectionList == null) { + return Collections.emptyList(); + } return sourceSectionList; } /** * Convenience method to get source sections according to a int line number. Returns a * collection of {@link SourceSection}s at the given line number. If there are no source - * sections at that line, a new empty list is returned. + * sections at that line, an empty list is returned. * * @param lineNumber The line number to check. - * @return A iterable collection of source sections at the given line. + * @return A collection of source sections at the given line. */ public Collection getSourceSectionsAtLineNumber(int lineNumber) { - ArrayList sourceSections = new ArrayList<>(); - for (LineLocation line : lineToSourceSectionsMap.keySet()) { + final Set keySet = lineToSourceSectionsMap.keySet(); + if (keySet.size() == 0) { + return Collections.emptyList(); + } + + final ArrayList sourceSections = new ArrayList<>(); + for (LineLocation line : keySet) { if (line.getLineNumber() == lineNumber) sourceSections.addAll(lineToSourceSectionsMap.get(line)); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/LoopNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/LoopNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/LoopNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -36,17 +36,17 @@ */ @Child protected Node repeatingNode; - public LoopNode(RepeatingNode repeatintNode) { - this.repeatingNode = (Node) repeatintNode; + public LoopNode(RepeatingNode repeatingNode) { + this.repeatingNode = (Node) repeatingNode; } public abstract void executeLoop(VirtualFrame frame); - protected final boolean executeRepeatNode(VirtualFrame frame) { - return getRepeatNode().executeRepeating(frame); + protected final boolean executeRepeatingNode(VirtualFrame frame) { + return getRepeatingNode().executeRepeating(frame); } - public final RepeatingNode getRepeatNode() { + public final RepeatingNode getRepeatingNode() { return (RepeatingNode) repeatingNode; } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java Thu Aug 28 17:49:37 2014 -0700 @@ -73,7 +73,7 @@ // TOOD (mlvdv) connect SourceSections into a spatial tree for fast geometric lookup // Files and pseudo files are indexed. - private static final Map> filePathToSource = new HashMap<>(); + private static final Map> filePathToSource = new Hashtable<>(); private static boolean fileCacheEnabled = true; @@ -171,6 +171,7 @@ return source; } + // TODO (mlvdv) enable per-file choice whether to cache? /** * Enables/disables caching of file contents, disabled by default. Caching of sources * created from literal text or readers is always enabled. diff -r c9c416d90a4e -r e4cfc9ea2bd3 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 Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Thu Aug 28 17:49:37 2014 -0700 @@ -34,7 +34,6 @@ import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.java.model.*; import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror; -import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.WildcardTypeMirror; /** * THIS IS NOT PUBLIC API. @@ -217,7 +216,7 @@ } public static boolean isSubtype(TypeMirror type1, TypeMirror type2) { - if (type1 instanceof CodeTypeMirror && type2 instanceof CodeTypeMirror) { + if (type1 instanceof CodeTypeMirror || type2 instanceof CodeTypeMirror) { throw new UnsupportedOperationException(); } return ProcessorContext.getInstance().getEnvironment().getTypeUtils().isSubtype(type1, type2); @@ -1046,11 +1045,7 @@ } int typeParameters = element.getTypeParameters().size(); if (typeParameters > 0 && declaredType.getTypeArguments().size() != typeParameters) { - List genericTypes = new ArrayList<>(); - for (int i = 0; i < typeParameters; i++) { - genericTypes.add(new WildcardTypeMirror(null, null)); - } - return new DeclaredCodeTypeMirror(element, genericTypes); + return ProcessorContext.getInstance().getEnvironment().getTypeUtils().erasure(type); } return type; } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java Thu Aug 28 17:49:37 2014 -0700 @@ -52,7 +52,7 @@ private static List sortBySourceOrder(List elements) { final Map> declarationOrders = new HashMap<>(); - Collections.sort(elements, new Comparator() { + Comparator comparator = new Comparator() { public int compare(Element o1, Element o2) { try { TypeMirror enclosing1 = o1.getEnclosingElement().asType(); @@ -60,6 +60,7 @@ if (ElementUtils.typeEquals(enclosing1, enclosing2)) { List declarationOrder = lookupDeclarationOrder(declarationOrders, (TypeElement) o1.getEnclosingElement()); + if (declarationOrder == null) { return 0; } @@ -69,21 +70,25 @@ int i1 = declarationOrder.indexOf(o1Binding); int i2 = declarationOrder.indexOf(o2Binding); + if (i1 == -1 || i2 == -1) { + return 0; + } + return i1 - i2; } else { if (ElementUtils.isSubtype(enclosing1, enclosing2)) { return 1; - } else if (ElementUtils.isSubtype(enclosing2, enclosing1)) { + } else { return -1; - } else { - return 0; } } } catch (Exception e) { throw new RuntimeException(e); } } - }); + }; + + Collections.sort(elements, comparator); return elements; } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java --- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java Thu Aug 28 17:49:37 2014 -0700 @@ -213,7 +213,7 @@ for (SLFunction function : functionList) { RootCallTarget rootCallTarget = function.getCallTarget(); - rootCallTarget.getRootNode().accept(new SLInstrumenter(slContext)); + rootCallTarget.getRootNode().accept(new SLInstrumenter()); } // We iterate over all tags the SLInsturmenter tagged as assignments and attach our diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -24,7 +24,6 @@ import java.math.*; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.*; @@ -92,18 +91,23 @@ } @Override - public Probe probe(ExecutionContext context) { + public Probe probe() { Node parent = getParent(); - if (parent == null) + if (parent == null) { throw new IllegalStateException("Cannot probe a node without a parent"); + } - if (parent instanceof SLExpressionWrapper) + if (parent instanceof SLExpressionWrapper) { return ((SLExpressionWrapper) parent).getProbe(); + } - SLExpressionWrapper wrapper = new SLExpressionWrapper((SLContext) context, this); + // Create a new wrapper/probe with this node as its child. + final SLExpressionWrapper wrapper = new SLExpressionWrapper(getRootNodeSLContext(this), this); + + // Replace this node in the AST with the wrapper this.replace(wrapper); - wrapper.insertChild(); + return wrapper.getProbe(); } } diff -r c9c416d90a4e -r e4cfc9ea2bd3 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 Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.sl.builtins.*; import com.oracle.truffle.sl.nodes.controlflow.*; +import com.oracle.truffle.sl.runtime.*; /** * The root of all SL execution trees. It is a Truffle requirement that the tree root extends the @@ -49,12 +50,16 @@ /** The name of the function, for printing purposes only. */ private final String name; - public SLRootNode(FrameDescriptor frameDescriptor, SLExpressionNode bodyNode, String name) { + /** The Simple execution context for this tree **/ + private final SLContext context; + + public SLRootNode(SLContext context, FrameDescriptor frameDescriptor, SLExpressionNode bodyNode, String name) { super(null, frameDescriptor); /* Deep copy the body before any specialization occurs during execution. */ this.uninitializedBodyNode = NodeUtil.cloneNode(bodyNode); this.bodyNode = bodyNode; this.name = name; + this.context = context; } @Override @@ -69,11 +74,15 @@ @Override public RootNode split() { - return new SLRootNode(getFrameDescriptor().shallowCopy(), NodeUtil.cloneNode(uninitializedBodyNode), name); + return new SLRootNode(this.context, getFrameDescriptor().shallowCopy(), NodeUtil.cloneNode(uninitializedBodyNode), name); } @Override public String toString() { return "root " + name; } + + public SLContext getSLContext() { + return this.context; + } } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java Thu Aug 28 17:49:37 2014 -0700 @@ -24,7 +24,6 @@ import java.io.*; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.nodes.*; @@ -87,18 +86,30 @@ } @Override - public Probe probe(ExecutionContext context) { + public Probe probe() { Node parent = getParent(); if (parent == null) throw new IllegalStateException("Cannot probe a node without a parent"); - if (parent instanceof SLStatementWrapper) + if (parent instanceof SLStatementWrapper) { return ((SLStatementWrapper) parent).getProbe(); + } - SLStatementWrapper wrapper = new SLStatementWrapper((SLContext) context, this); + // Create a new wrapper/probe with this node as its child. + final SLStatementWrapper wrapper = new SLStatementWrapper(getRootNodeSLContext(this), this); + + // Replace this node in the AST with the wrapper this.replace(wrapper); - wrapper.insertChild(); + return wrapper.getProbe(); } + + protected SLContext getRootNodeSLContext(Node node) { + assert node != null; + + if (node instanceof SLRootNode) + return ((SLRootNode) node).getSLContext(); + return getRootNodeSLContext(node.getParent()); + } } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java Thu Aug 28 17:49:37 2014 -0700 @@ -32,15 +32,12 @@ import com.oracle.truffle.sl.runtime.*; /** - * SLExpressionWrapper is a Truffle AST node that gets inserted as the parent to the node that it is - * wrapping. Any debugging instruments are attached to this wrapper through {@link Probe}s (which - * themselves contain the instruments. It is through this mechanism that tools can interact directly - * with the AST.
- * {@link SLExpressionWrapper} specifically wraps {@link SLExpressionNode}s and overrides the - * various execute functions in {@link SLExpressionNode} to operate on the child of the wrapper - * instead of the wrapper itself. - * + * A Truffle node that can be inserted into a Simple AST (assumed not to have executed yet) to + * enable "instrumentation" of an {@link SLExpressionNode}. Tools wishing to interact with AST + * execution may attach {@link Instrument}s to the {@link Probe} uniquely associated with the + * wrapper, and to which this wrapper routes {@link ExecutionEvents}. */ + public final class SLExpressionWrapper extends SLExpressionNode implements Wrapper { @Child private SLExpressionNode child; @@ -154,10 +151,4 @@ return SLTypesGen.SLTYPES.expectSLNull(executeGeneric(frame)); } - /** - * Sets the parent pointer of this wrapper's child. - */ - public void insertChild() { - insert(this.child); - } } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLInstrumenter.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLInstrumenter.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLInstrumenter.java Thu Aug 28 17:49:37 2014 -0700 @@ -29,20 +29,14 @@ import com.oracle.truffle.sl.nodes.*; import com.oracle.truffle.sl.nodes.controlflow.*; import com.oracle.truffle.sl.nodes.local.*; -import com.oracle.truffle.sl.runtime.*; /** - * This is a general purpose visitor which traverses a completely parsed Simple AST and instruments - * all the nodes within it. This visitor is designed to visit the tree immediately after it has been - * parsed. - * + * A visitor which traverses a completely parsed Simple AST (presumed not yet executed) and + * instruments some of them. */ public class SLInstrumenter implements NodeVisitor { - private final SLContext context; - - public SLInstrumenter(SLContext context) { - this.context = context; + public SLInstrumenter() { } /** @@ -57,7 +51,7 @@ if (node instanceof SLExpressionNode && node.getParent() != null) { SLExpressionNode expressionNode = (SLExpressionNode) node; if (expressionNode.getSourceSection() != null) { - Probe probe = expressionNode.probe(context); + Probe probe = expressionNode.probe(); // probe.tagAs(STATEMENT); if (node instanceof SLWriteLocalVariableNode) @@ -67,7 +61,7 @@ SLStatementNode statementNode = (SLStatementNode) node; if (statementNode.getSourceSection() != null) { - Probe probe = statementNode.probe(context); + Probe probe = statementNode.probe(); probe.tagAs(STATEMENT); if (node instanceof SLWhileNode) diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLNodeProber.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLNodeProber.java Thu Aug 28 17:15:23 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2012, 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.nodes.instrument; - -import com.oracle.truffle.api.instrument.*; -import com.oracle.truffle.sl.nodes.*; - -public interface SLNodeProber extends ASTNodeProber { - - SLStatementNode probeAsStatement(SLStatementNode result); - - SLExpressionNode probeAsCall(SLExpressionNode node, String callName); - - SLExpressionNode probeAsLocalAssignment(SLExpressionNode node, String localName); -} diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java Thu Aug 28 17:49:37 2014 -0700 @@ -30,14 +30,10 @@ import com.oracle.truffle.sl.runtime.*; /** - * SLStatmentWrapper is a Truffle AST node that gets inserted as the parent to the node that it is - * wrapping. Any debugging instruments are attached to this wrapper through {@link Probe}s (which - * themselves contain the instruments). It is through this mechanism that tools can interact - * directly with the AST.
- * SLStatmentWrapper specifically wraps {@link SLStatementWrapper}s and overrides the executeVoid - * function of {@link SLStatementNode} to operate on the child of the wrapper instead of the wrapper - * itself. - * + * A Truffle node that can be inserted into a Simple AST (assumed not to have executed yet) to + * enable "instrumentation" of a {@link SLStatementNode}. Tools wishing to interact with AST + * execution may attach {@link Instrument}s to the {@link Probe} uniquely associated with the + * wrapper, and to which this wrapper routes {@link ExecutionEvents}. */ public final class SLStatementWrapper extends SLStatementNode implements Wrapper { @@ -50,8 +46,6 @@ assert !(child instanceof SLStatementWrapper); this.probe = context.createProbe(child.getSourceSection()); this.child = child; - // The child should only be inserted after a replace, so we defer inserting the child to the - // creator of the wrapper. } @Override @@ -98,10 +92,4 @@ } } - /** - * Sets the parent pointer of this wrapper's child. - */ - public void insertChild() { - insert(this.child); - } } diff -r c9c416d90a4e -r e4cfc9ea2bd3 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Thu Aug 28 17:49:37 2014 -0700 @@ -115,7 +115,7 @@ assert lexicalScope == null : "Wrong scoping of blocks in parser"; final SLFunctionBodyNode functionBodyNode = new SLFunctionBodyNode(functionSrc, methodBlock); - final SLRootNode rootNode = new SLRootNode(frameDescriptor, functionBodyNode, functionName); + final SLRootNode rootNode = new SLRootNode(this.context, frameDescriptor, functionBodyNode, functionName); context.getFunctionRegistry().register(functionName, rootNode); diff -r c9c416d90a4e -r e4cfc9ea2bd3 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 Thu Aug 28 17:15:23 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java Thu Aug 28 17:49:37 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.truffle.sl.runtime; import java.io.*; +import java.util.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; @@ -33,6 +34,7 @@ import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.builtins.*; import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.nodes.local.*; import com.oracle.truffle.sl.parser.*; @@ -130,7 +132,7 @@ /* The name of the builtin function is specified via an annotation on the node class. */ String name = builtinBodyNode.getClass().getAnnotation(NodeInfo.class).shortName(); /* Wrap the builtin in a RootNode. Truffle requires all AST to start with a RootNode. */ - SLRootNode rootNode = new SLRootNode(new FrameDescriptor(), builtinBodyNode, name); + SLRootNode rootNode = new SLRootNode(this, new FrameDescriptor(), builtinBodyNode, name); /* Register the builtin function in our function registry. */ getFunctionRegistry().register(name, rootNode); @@ -154,6 +156,17 @@ Parser.parseSL(this, source); + List functionList = getFunctionRegistry().getFunctions(); + + // Since only functions can be global in SL, this guarantees that we instrument + // everything of interest. Parsing must occur before accepting the visitors since + // the visitor which creates our instrumentation points expects a complete AST. + + for (SLFunction function : functionList) { + RootCallTarget rootCallTarget = function.getCallTarget(); + rootCallTarget.getRootNode().accept(new SLInstrumenter()); + } + if (sourceCallback != null) { sourceCallback.endLoading(source); } diff -r c9c416d90a4e -r e4cfc9ea2bd3 mx/mx_graal.py --- a/mx/mx_graal.py Thu Aug 28 17:15:23 2014 -0700 +++ b/mx/mx_graal.py Thu Aug 28 17:49:37 2014 -0700 @@ -1059,7 +1059,7 @@ else: return [], args -def _run_tests(args, harness, annotations, testfile, whitelist, regex): +def _run_tests(args, harness, annotations, testfile, blacklist, whitelist, regex): vmArgs, tests = _extract_VM_args(args) @@ -1106,6 +1106,9 @@ mx.log('warning: no tests matched by substring "' + t) projectsCp = mx.classpath(projs) + if blacklist: + classes = [c for c in classes if not any((glob.match(c) for glob in blacklist))] + if whitelist: classes = [c for c in classes if any((glob.match(c) for glob in whitelist))] @@ -1119,7 +1122,7 @@ f_testfile.close() harness(projectsCp, vmArgs) -def _unittest(args, annotations, prefixCp="", whitelist=None, verbose=False, enable_timing=False, regex=None, color=False, eager_stacktrace=False, gc_after_test=False): +def _unittest(args, annotations, prefixCp="", blacklist=None, whitelist=None, verbose=False, enable_timing=False, regex=None, color=False, eager_stacktrace=False, gc_after_test=False): testfile = os.environ.get('MX_TESTFILE', None) if testfile is None: (_, testfile) = tempfile.mkstemp(".testclasses", "graal") @@ -1169,7 +1172,7 @@ vm(prefixArgs + vmArgs + ['-cp', cp, 'com.oracle.graal.test.GraalJUnitCore'] + coreArgs + ['@' + testfile]) try: - _run_tests(args, harness, annotations, testfile, whitelist, regex) + _run_tests(args, harness, annotations, testfile, blacklist, whitelist, regex) finally: if os.environ.get('MX_TESTFILE') is None: os.remove(testfile) @@ -1177,6 +1180,7 @@ _unittestHelpSuffix = """ Unittest options: + --blacklist run all testcases not specified in the blacklist --whitelist run only testcases which are included in the given whitelist --verbose enable verbose JUnit output @@ -1221,6 +1225,7 @@ formatter_class=RawDescriptionHelpFormatter, epilog=_unittestHelpSuffix, ) + parser.add_argument('--blacklist', help='run all testcases not specified in the blacklist', metavar='') parser.add_argument('--whitelist', help='run testcases specified in whitelist only', metavar='') parser.add_argument('--verbose', help='enable verbose JUnit output', action='store_true') parser.add_argument('--enable-timing', help='enable JUnit test timing', action='store_true') @@ -1252,6 +1257,12 @@ parsed_args.whitelist = [re.compile(fnmatch.translate(l.rstrip())) for l in fp.readlines() if not l.startswith('#')] except IOError: mx.log('warning: could not read whitelist: ' + parsed_args.whitelist) + if parsed_args.blacklist: + try: + with open(join(_graal_home, parsed_args.blacklist)) as fp: + parsed_args.blacklist = [re.compile(fnmatch.translate(l.rstrip())) for l in fp.readlines() if not l.startswith('#')] + except IOError: + mx.log('warning: could not read blacklist: ' + parsed_args.blacklist) _unittest(args, ['@Test', '@Parameters'], **parsed_args.__dict__) @@ -1952,8 +1963,12 @@ 'intel/hsdis-amd64.dylib' : 'fdb13ef0d7d23d93dacaae9c98837bea0d4fc5a2', } + flavoredLib = flavor + "/" + lib + if flavoredLib not in sha1s: + mx.logv("hsdis not supported on this plattform or architecture") + return + if not exists(path): - flavoredLib = flavor + "/" + lib sha1 = sha1s[flavoredLib] sha1path = path + '.sha1' mx.download_file_with_sha1('hsdis', path, ['http://lafo.ssw.uni-linz.ac.at/hsdis/' + flavoredLib], sha1, sha1path, True, True, sources=False) diff -r c9c416d90a4e -r e4cfc9ea2bd3 mx/projects --- a/mx/projects Thu Aug 28 17:15:23 2014 -0700 +++ b/mx/projects Thu Aug 28 17:49:37 2014 -0700 @@ -390,7 +390,7 @@ # graal.lir project@com.oracle.graal.lir@subDir=graal project@com.oracle.graal.lir@sourceDirs=src -project@com.oracle.graal.lir@dependencies=com.oracle.graal.debug,com.oracle.graal.compiler.common,com.oracle.graal.asm +project@com.oracle.graal.lir@dependencies=com.oracle.graal.compiler.common,com.oracle.graal.asm,com.oracle.graal.debug project@com.oracle.graal.lir@checkstyle=com.oracle.graal.graph project@com.oracle.graal.lir@javaCompliance=1.8 project@com.oracle.graal.lir@workingSets=Graal,LIR diff -r c9c416d90a4e -r e4cfc9ea2bd3 mxtool/mx.py --- a/mxtool/mx.py Thu Aug 28 17:15:23 2014 -0700 +++ b/mxtool/mx.py Thu Aug 28 17:49:37 2014 -0700 @@ -1247,11 +1247,11 @@ """ Get the list of all loaded projects limited by --suite option if opt_limit_to_suite == True """ - + sortedProjects = sorted(_projects.values(), key=lambda p: p.name) if opt_limit_to_suite: - return _projects_opt_limit_to_suites(_projects.values()) + return _projects_opt_limit_to_suites(sortedProjects) else: - return _projects.values() + return sortedProjects def projects_opt_limit_to_suites(): """ @@ -2231,8 +2231,13 @@ self.proj.definedAnnotationProcessorsDist.make_archive() finally: - for n in toBeDeleted: - os.remove(n) + # Do not clean up temp files if verbose as there's + # a good chance the user wants to copy and paste the + # Java compiler command directly + if not _opts.verbose: + for n in toBeDeleted: + os.remove(n) + self.done = True def build(args, parser=None): @@ -2413,6 +2418,8 @@ logv('[no Java sources for {0} - skipping]'.format(p.name)) continue + javafilelist = sorted(javafilelist) + task = JavaCompileTask(args, p, buildReason, javafilelist, jdk, outputDir, jdtJar, taskDeps) if p.definedAnnotationProcessorsDist: updatedAnnotationProcessorDists.add(p.definedAnnotationProcessorsDist) diff -r c9c416d90a4e -r e4cfc9ea2bd3 test/blacklist_sparc.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/blacklist_sparc.txt Thu Aug 28 17:49:37 2014 -0700 @@ -0,0 +1,310 @@ +com.oracle.graal.jtt.lang.Object_equals01 +com.oracle.graal.replacements.test.CheckCastTest +com.oracle.graal.hotspot.test.AheadOfTimeCompilationTest +com.oracle.graal.jtt.reflect.Invoke_except01 +com.oracle.graal.jtt.bytecode.BC_fastore +com.oracle.graal.compiler.test.deopt.MonitorDeoptTest +com.oracle.graal.jtt.loop.LoopParseLong +com.oracle.graal.jtt.bytecode.BC_baload +com.oracle.graal.jtt.threads.ThreadLocal01 +com.oracle.graal.jtt.jdk.UnsafeAllocateInstance01 +com.oracle.graal.jtt.threads.ThreadLocal02 +com.oracle.graal.jtt.optimize.ConditionalElimination01 +com.oracle.graal.jtt.threads.ThreadLocal03 +com.oracle.graal.jtt.except.BC_athrow3 +com.oracle.graal.jtt.except.BC_checkcast +com.oracle.graal.jtt.micro.VarArgs_short01 +com.oracle.graal.replacements.test.InvokeTest +com.oracle.graal.jtt.reflect.Invoke_virtual01 +com.oracle.graal.jtt.lang.Math_cos +com.oracle.graal.jtt.lang.Math_log10 +com.oracle.graal.jtt.optimize.Narrow_char02 +com.oracle.graal.jtt.lang.Math_sin +com.oracle.graal.jtt.bytecode.BC_lookupswitch05 +com.oracle.graal.jtt.except.BC_aastore0 +com.oracle.graal.jtt.reflect.Class_getDeclaredField01 +com.oracle.graal.jtt.micro.VarArgs_double01 +com.oracle.graal.jtt.micro.String_format02 +com.oracle.graal.compiler.hsail.test.lambda.ArrayListSetTest +com.oracle.graal.jtt.optimize.List_reorder_bug +com.oracle.graal.jtt.hotpath.HP_idea +com.oracle.graal.jtt.except.Throw_Synchronized01 +com.oracle.graal.jtt.lang.Bridge_method01 +com.oracle.graal.compiler.test.IfReorderTest +com.oracle.graal.jtt.optimize.Switch02 +com.oracle.graal.jtt.jdk.Thread_setName +com.oracle.graal.jtt.reflect.Array_set01 +com.oracle.graal.jtt.reflect.Array_set02 +com.oracle.graal.jtt.except.BC_checkcast5 +com.oracle.graal.jtt.micro.VarArgs_float01 +com.oracle.graal.jtt.bytecode.BC_monitorenter +com.oracle.graal.jtt.hotpath.HP_array04 +com.oracle.graal.compiler.hsail.test.lambda.StringSubstringTest +com.oracle.graal.jtt.hotpath.HP_array03 +com.oracle.graal.jtt.hotpath.HP_array02 +com.oracle.graal.jtt.threads.Thread_isInterrupted03 +com.oracle.graal.jtt.threads.Thread_isInterrupted02 +com.oracle.graal.jtt.threads.Thread_isInterrupted05 +com.oracle.graal.jtt.lang.ClassLoader_loadClass01 +com.oracle.graal.jtt.optimize.NCE_02 +com.oracle.graal.jtt.lang.Object_hashCode01 +com.oracle.graal.jtt.loop.Loop09 +com.oracle.graal.compiler.hsail.test.lambda.DremTest +com.oracle.graal.replacements.test.StandardMethodSubstitutionsTest +com.oracle.graal.jtt.jdk.UnsafeAccess01 +com.oracle.graal.jtt.loop.LoopSwitch01 +com.oracle.graal.jtt.except.Catch_NASE_2 +com.oracle.graal.jtt.threads.Thread_setPriority01 +com.oracle.graal.jtt.except.BC_checkcast3 +com.oracle.graal.jtt.reflect.Invoke_main03 +com.oracle.graal.jtt.except.BC_aastore1 +com.oracle.graal.jtt.except.BC_saload +com.oracle.graal.jtt.threads.Monitor_contended01 +com.oracle.graal.jtt.lang.Class_getName02 +com.oracle.graal.jtt.reflect.Invoke_main01 +com.oracle.graal.jtt.lang.Math_sqrt +com.oracle.graal.jtt.bytecode.BC_ldc_06 +com.oracle.graal.jtt.optimize.ConditionalElimination02 +com.oracle.graal.jtt.lang.String_intern02 +com.oracle.truffle.sl.test.SLSimpleTestSuite +com.oracle.graal.jtt.micro.Bubblesort +com.oracle.graal.jtt.lang.String_intern03 +com.oracle.graal.jtt.hotpath.HP_demo01 +com.oracle.graal.jtt.optimize.ArrayLength01 +com.oracle.graal.replacements.test.DynamicNewArrayTest +com.oracle.graal.jtt.micro.InvokeVirtual_02 +com.oracle.graal.jtt.lang.Object_getClass01 +com.oracle.graal.jtt.micro.Matrix01 +com.oracle.graal.replacements.test.NewInstanceTest +com.oracle.graal.jtt.lang.Class_getSimpleName01 +com.oracle.graal.jtt.lang.Class_getSimpleName02 +com.oracle.graal.jtt.bytecode.BC_d2l02 +com.oracle.graal.jtt.except.BC_checkcast6 +com.oracle.graal.jtt.lang.Class_getSuperClass01 +com.oracle.graal.jtt.lang.Class_getInterfaces01 +com.oracle.graal.jtt.lang.Class_Literal01 +com.oracle.graal.replacements.test.StringSubstitutionsTest +com.oracle.graal.jtt.except.BC_checkcast4 +com.oracle.graal.jtt.bytecode.BC_f2l02 +com.oracle.graal.jtt.micro.VarArgs_long01 +com.oracle.graal.compiler.test.ea.UnsafeEATest +com.oracle.graal.jtt.except.Catch_NASE_1 +com.oracle.graal.jtt.bytecode.BC_iastore +com.oracle.graal.compiler.test.ShortCircuitNodeTest +com.oracle.graal.jtt.threads.Thread_isInterrupted04 +com.oracle.graal.jtt.jdk.EnumMap02 +com.oracle.graal.jtt.threads.Monitor_notowner01 +com.oracle.graal.hotspot.test.ArrayCopyIntrinsificationTest +com.oracle.graal.jtt.bytecode.BC_putfield_01 +com.oracle.graal.jtt.lang.Math_tan +com.oracle.graal.jtt.bytecode.BC_aaload +com.oracle.graal.jtt.optimize.Narrow_short03 +com.oracle.graal.jtt.optimize.Narrow_short02 +com.oracle.graal.jtt.optimize.ArrayCopy01 +com.oracle.graal.jtt.bytecode.BC_athrow +com.oracle.graal.jtt.except.BC_sastore +com.oracle.graal.jtt.bytecode.BC_d2i02 +com.oracle.graal.jtt.threads.Object_wait01 +com.oracle.graal.jtt.bytecode.BC_sastore +com.oracle.graal.jtt.bytecode.BC_l2i_2 +com.oracle.graal.jtt.micro.BigObjectParams02 +com.oracle.graal.jtt.except.StackTrace_NPE_01 +com.oracle.graal.compiler.test.CommonedConstantsTest +com.oracle.graal.jtt.bytecode.BC_getfield +com.oracle.graal.jtt.bytecode.BC_laload +com.oracle.graal.hotspot.test.WriteBarrierAdditionTest +com.oracle.graal.jtt.hotpath.HP_life +com.oracle.graal.hotspot.test.CRC32SubstitutionsTest +com.oracle.graal.jtt.lang.Boxed_TYPE_01 +com.oracle.graal.jtt.reflect.Class_getDeclaredMethod01 +com.oracle.graal.jtt.threads.Thread_new02 +com.oracle.graal.jtt.threads.Thread_new01 +com.oracle.graal.jtt.except.BC_caload +com.oracle.graal.compiler.hsail.test.StaticMethod16InArraysTest +com.oracle.graal.jtt.jdk.Unsafe_compareAndSwap +com.oracle.graal.replacements.test.MonitorTest +com.oracle.graal.jtt.except.Throw_Synchronized05 +com.oracle.graal.jtt.reflect.Array_newInstance02 +com.oracle.graal.jtt.reflect.Array_newInstance03 +com.oracle.graal.jtt.reflect.Array_newInstance01 +com.oracle.graal.jtt.reflect.Array_newInstance06 +com.oracle.graal.jtt.micro.VarArgs_byte01 +com.oracle.graal.jtt.except.BC_laload +com.oracle.graal.compiler.test.ea.EscapeAnalysisTest +com.oracle.graal.jtt.except.Throw_Synchronized02 +com.oracle.graal.jtt.except.Throw_Synchronized04 +com.oracle.graal.jtt.optimize.NestedLoop_EA +com.oracle.graal.jtt.except.BC_newarray +com.oracle.graal.jtt.loop.Loop15 +com.oracle.graal.compiler.hsail.test.lambda.ObjectArrayInstanceDerivedTest +com.oracle.graal.jtt.bytecode.BC_checkcast01 +com.oracle.graal.jtt.except.BC_anewarray +com.oracle.graal.hotspot.amd64.test.CompressedNullCheckTest +com.oracle.graal.compiler.test.MemoryArithmeticTest +com.oracle.graal.jtt.bytecode.BC_getfield_o +com.oracle.graal.jtt.lang.Class_getComponentType01 +com.oracle.graal.jtt.reflect.Array_newInstance04 +com.oracle.graal.jtt.reflect.Method_getParameterTypes01 +com.oracle.graal.compiler.test.inlining.InliningTest +com.oracle.graal.hotspot.test.InstalledCodeExecuteHelperTest +com.oracle.graal.jtt.except.BC_castore +com.oracle.graal.jtt.lang.Class_isInstance06 +com.oracle.graal.jtt.lang.Class_isInstance07 +com.oracle.graal.jtt.threads.Thread_join03 +com.oracle.graal.jtt.threads.Thread_join01 +com.oracle.graal.jtt.except.BC_putfield +com.oracle.graal.jtt.lang.Class_forName03 +com.oracle.graal.jtt.lang.Class_forName04 +com.oracle.graal.jtt.lang.Class_forName05 +com.oracle.graal.jtt.hotspot.Test6186134 +com.oracle.graal.jtt.optimize.NCE_03 +com.oracle.graal.jtt.micro.String_format01 +com.oracle.graal.jtt.except.BC_lastore +com.oracle.graal.jtt.bytecode.BC_monitorenter02 +com.oracle.graal.jtt.micro.ReferenceMap01 +com.oracle.graal.jtt.bytecode.BC_instanceof +com.oracle.graal.jtt.except.Catch_Unresolved +com.oracle.graal.compiler.test.MemoryScheduleTest +com.oracle.graal.jtt.bytecode.BC_castore +com.oracle.graal.jtt.except.Throw_InCatch03 +com.oracle.graal.jtt.except.Throw_InCatch02 +com.oracle.graal.jtt.except.Throw_InCatch01 +com.oracle.graal.jtt.except.BC_iaload +com.oracle.graal.jtt.lang.Double_toString +com.oracle.graal.jtt.optimize.ABCE_02 +com.oracle.graal.replacements.test.CompiledExceptionHandlerTest +com.oracle.graal.jtt.except.Throw_Synchronized03 +com.oracle.graal.jtt.threads.Thread_join02 +com.oracle.graal.jtt.threads.SynchronizedLoopExit01 +com.oracle.graal.jtt.bytecode.BC_daload +com.oracle.graal.jtt.optimize.Conditional01 +com.oracle.graal.jtt.lang.JDK_ClassLoaders02 +com.oracle.graal.jtt.bytecode.BC_putfield_03 +com.oracle.graal.jtt.bytecode.BC_putfield_02 +com.oracle.graal.jtt.micro.BigInterfaceParams01 +com.oracle.graal.jtt.micro.VarArgs_String01 +com.oracle.graal.jtt.optimize.LongToSomethingArray01 +com.oracle.graal.jtt.except.BC_checkcast1 +com.oracle.graal.jtt.except.Catch_NPE_07 +com.oracle.graal.jtt.except.Catch_NPE_06 +com.oracle.graal.jtt.except.Catch_NPE_02 +com.oracle.graal.jtt.except.Catch_NPE_01 +com.oracle.graal.replacements.test.ArraysSubstitutionsTest +com.oracle.graal.jtt.except.StackTrace_CCE_00 +com.oracle.graal.jtt.lang.ProcessEnvironment_init +com.oracle.graal.jtt.except.BC_bastore +com.oracle.graal.jtt.except.BC_baload +com.oracle.graal.jtt.lang.Class_asSubclass01 +com.oracle.graal.jtt.bytecode.BC_invokevirtual +com.oracle.graal.compiler.test.BoxingEliminationTest +com.oracle.graal.compiler.test.deopt.CompiledMethodTest +com.oracle.graal.compiler.ptx.test.ArrayPTXTest +com.oracle.graal.jtt.reflect.Class_getMethod01 +com.oracle.graal.compiler.test.InfopointReasonTest +com.oracle.graal.jtt.reflect.Class_getMethod02 +com.oracle.graal.jtt.bytecode.BC_invokespecial2 +com.oracle.graal.jtt.reflect.Method_getReturnType01 +com.oracle.graal.replacements.test.InstanceOfTest +com.oracle.graal.jtt.bytecode.BC_invokespecial +com.oracle.graal.jtt.lang.Object_toString02 +com.oracle.graal.jtt.lang.Object_toString01 +com.oracle.graal.jtt.jdk.EnumMap01 +com.oracle.graal.jtt.except.BC_checkcast2 +com.oracle.graal.replacements.test.InstanceOfDynamicTest +com.oracle.graal.hotspot.test.HotSpotNodeSubstitutionsTest +com.oracle.graal.replacements.test.UnsignedMathTest +com.oracle.graal.jtt.reflect.Field_get03 +com.oracle.graal.jtt.bytecode.BC_putfield_04 +com.oracle.graal.hotspot.test.CompressedOopTest +com.oracle.graal.jtt.except.BC_daload +com.oracle.graal.hotspot.amd64.test.AMD64HotSpotFrameOmissionTest +com.oracle.graal.jtt.hotpath.HP_allocate04 +com.oracle.graal.jtt.hotpath.HP_allocate03 +com.oracle.graal.jtt.optimize.NCE_01 +com.oracle.graal.jtt.optimize.NCE_04 +com.oracle.graal.jtt.lang.Class_getName01 +com.oracle.graal.hotspot.test.HotSpotMonitorValueTest +com.oracle.graal.jtt.threads.Thread_getState02 +com.oracle.graal.jtt.except.BC_arraylength +com.oracle.graal.jtt.bytecode.BC_caload +com.oracle.graal.replacements.test.UnsafeSubstitutionsTest +com.oracle.graal.jtt.bytecode.BC_saload +com.oracle.graal.hotspot.test.HotSpotNmethodTest +com.oracle.graal.replacements.test.DeoptimizeOnExceptionTest +com.oracle.graal.jtt.optimize.ArrayCopyGeneric +com.oracle.graal.jtt.lang.Class_forName01 +com.oracle.graal.jtt.except.BC_monitorenter +com.oracle.graal.jtt.except.Catch_Loop02 +com.oracle.graal.jtt.bytecode.BC_lastore +com.oracle.graal.jtt.except.BC_getfield +com.oracle.graal.jtt.except.BC_aaload1 +com.oracle.graal.jtt.except.BC_aaload0 +com.oracle.graal.jtt.except.BC_dastore +com.oracle.graal.jtt.micro.VarArgs_char01 +com.oracle.graal.jtt.optimize.NCE_FlowSensitive05 +com.oracle.graal.jtt.optimize.NCE_FlowSensitive03 +com.oracle.graal.jtt.bytecode.BC_aaload_1 +com.oracle.graal.jtt.lang.Math_abs +com.oracle.graal.hotspot.test.CompileTheWorldTest +com.oracle.graal.jtt.micro.FloatingReads +com.oracle.graal.jtt.except.BC_fastore +com.oracle.graal.jtt.optimize.ArrayCopy05 +com.oracle.graal.jtt.bytecode.BC_aastore +com.oracle.graal.compiler.test.LockEliminationTest +com.oracle.graal.jtt.hotpath.HP_invoke01 +com.oracle.graal.jtt.bytecode.BC_dastore +com.oracle.graal.jtt.loop.DegeneratedLoop +com.oracle.graal.jtt.hotpath.HP_array01 +com.oracle.graal.jtt.except.BC_iastore +com.oracle.graal.jtt.except.BC_athrow2 +com.oracle.graal.jtt.except.BC_athrow0 +com.oracle.graal.jtt.except.BC_athrow1 +com.oracle.graal.jtt.micro.VarArgs_int01 +com.oracle.graal.jtt.micro.BigVirtualParams01 +com.oracle.graal.jtt.jdk.Class_getName +com.oracle.graal.jtt.reflect.Array_newInstance05 +com.oracle.graal.jtt.optimize.ABCE_01 +com.oracle.graal.jtt.micro.InvokeVirtual_01 +com.oracle.graal.jtt.except.StackTrace_AIOOBE_00 +com.oracle.graal.jtt.bytecode.BC_invokeinterface +com.oracle.graal.jtt.micro.BigMixedParams04 +com.oracle.graal.jtt.reflect.Invoke_main02 +com.oracle.graal.jtt.threads.Object_wait02 +com.oracle.graal.jtt.threads.Object_wait03 +com.oracle.graal.jtt.threads.Object_wait04 +com.oracle.graal.jtt.except.Catch_Unresolved02 +com.oracle.graal.jtt.except.Catch_Unresolved03 +com.oracle.graal.compiler.test.CheckGraalInvariants +com.oracle.graal.jtt.except.Catch_Unresolved01 +com.oracle.graal.jtt.optimize.Narrow_byte03 +com.oracle.graal.jtt.except.BC_faload +com.oracle.graal.nodes.test.LoopPhiCanonicalizerTest +com.oracle.graal.jtt.bytecode.BC_f2i02 +com.oracle.graal.jtt.bytecode.BC_iaload +com.oracle.graal.jtt.reflect.Array_set03 +com.oracle.graal.jtt.lang.Class_forName02 +com.oracle.graal.compiler.hsail.test.lambda.ObjectArrayInstanceTest +com.oracle.graal.jtt.micro.VarArgs_boolean01 +com.oracle.graal.jtt.lang.Math_log +com.oracle.graal.compiler.test.FlowSensitiveReductionTest +com.oracle.graal.jtt.bytecode.BC_faload +com.oracle.graal.jtt.bytecode.BC_multianewarray03 +com.oracle.graal.jtt.loop.Loop06 +com.oracle.graal.jtt.loop.Loop07 +com.oracle.graal.jtt.loop.Loop13 +com.oracle.graal.jtt.bytecode.BC_bastore +com.oracle.graal.jtt.except.Catch_Two02 +com.oracle.graal.jtt.except.Catch_Two03 +com.oracle.graal.jtt.except.Catch_Two01 +com.oracle.graal.jtt.optimize.Narrow_byte02 +com.oracle.graal.jtt.loop.Loop05 +com.oracle.graal.jtt.loop.Loop12 +com.oracle.graal.jtt.jdk.System_setOut +com.oracle.graal.jtt.except.Catch_Loop03 +com.oracle.graal.jtt.micro.BC_invokevirtual2 +com.oracle.graal.jtt.optimize.Narrow_char03 +com.oracle.graal.jtt.optimize.ArrayCopy02 +com.oracle.graal.jtt.optimize.ArrayCopy04 +com.oracle.graal.jtt.optimize.ArrayCopy06 +com.oracle.graal.replacements.test.NewArrayTest +com.oracle.graal.jtt.optimize.ArrayCopy03