# HG changeset patch # User Doug Simon # Date 1401304636 -7200 # Node ID 5d0fbc245e55d7827ebcfaf448d4d86e1b847576 # Parent 42eaa579e134aea6bd12ef13b4ab731910f3967d# Parent 9d7b2134c4cefdcbcf080a956697b7332efca648 Merge. diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java Wed May 28 21:17:16 2014 +0200 @@ -86,7 +86,7 @@ Class currentClazz = clazz; do { for (Field field : currentClazz.getDeclaredFields()) { - if (Modifier.isStatic(field.getModifiers())) { + if (Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers())) { continue; } Class type = field.getType(); diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Wed May 28 21:17:16 2014 +0200 @@ -208,6 +208,9 @@ if (!(otherStamp instanceof IntegerStamp)) { return StampFactory.illegal(Kind.Illegal); } + if (equals(otherStamp)) { + return this; + } IntegerStamp other = (IntegerStamp) otherStamp; return createStamp(other, Math.max(upperBound, other.upperBound), Math.min(lowerBound, other.lowerBound), downMask & other.downMask, upMask | other.upMask); } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java --- a/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java Wed May 28 21:17:16 2014 +0200 @@ -111,7 +111,7 @@ DebugHistogram histogram = Debug.createHistogram("TestHistogram"); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); histogram.add("MyCustomValue"); - new DebugHistogramAsciiPrinter(new PrintStream(outputStream), Integer.MAX_VALUE, 10, 10).print(histogram); + new DebugHistogramAsciiPrinter(new PrintStream(outputStream), Integer.MAX_VALUE, 10, 10, 1).print(histogram); String[] lines = outputStream.toString().split("\n"); Assert.assertEquals(4, lines.length); Assert.assertEquals("TestHistogram has 1 unique elements and 1 total elements:", lines[0]); diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java Wed May 28 21:17:16 2014 +0200 @@ -40,16 +40,18 @@ */ void add(Object value); + void add(Object value, long count); + /** * A value and a frequency. The ordering imposed by {@link #compareTo(CountedValue)} places * values with higher frequencies first. */ public class CountedValue implements Comparable { - private int count; + private long count; private final Object value; - public CountedValue(int count, Object value) { + public CountedValue(long count, Object value) { this.count = count; this.value = value; } @@ -72,11 +74,11 @@ count++; } - public void add(int n) { + public void add(long n) { count += n; } - public int getCount() { + public long getCount() { return count; } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramAsciiPrinter.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramAsciiPrinter.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramAsciiPrinter.java Wed May 28 21:17:16 2014 +0200 @@ -37,14 +37,16 @@ public static final int NumberSize = 10; public static final int DefaultNameSize = 50; public static final int DefaultBarSize = 100; + public static final int DefaultScale = 1; - private PrintStream os; - private int limit; - private int nameSize; - private int barSize; + private final PrintStream os; + private final int limit; + private final int nameSize; + private final int barSize; + private final int scale; public DebugHistogramAsciiPrinter(PrintStream os) { - this(os, Integer.MAX_VALUE, DefaultNameSize, DefaultBarSize); + this(os, Integer.MAX_VALUE, DefaultNameSize, DefaultBarSize, DefaultScale); } /** @@ -52,12 +54,14 @@ * @param limit limits printing to the {@code limit} most frequent values * @param nameSize the width of the value names column * @param barSize the width of the value frequency column + * @param scale a factor by which every result is divided */ - public DebugHistogramAsciiPrinter(PrintStream os, int limit, int nameSize, int barSize) { + public DebugHistogramAsciiPrinter(PrintStream os, int limit, int nameSize, int barSize, int scale) { this.os = os; this.limit = limit; this.nameSize = nameSize; this.barSize = barSize; + this.scale = scale; } public void print(DebugHistogram histogram) { @@ -68,21 +72,18 @@ } // Sum up the total number of elements. - int total = 0; - for (CountedValue cv : list) { - total += cv.getCount(); - } + long total = list.stream().mapToLong(CountedValue::getCount).sum(); // Print header. - os.printf("%s has %d unique elements and %d total elements:%n", histogram.getName(), list.size(), total); + os.printf("%s has %d unique elements and %d total elements:%n", histogram.getName(), list.size(), total / scale); - int max = list.get(0).getCount(); + long max = list.get(0).getCount() / scale; final int lineSize = nameSize + NumberSize + barSize + 10; printLine(os, '-', lineSize); String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n"; for (int i = 0; i < list.size() && i < limit; ++i) { CountedValue cv = list.get(i); - int value = cv.getCount(); + long value = cv.getCount() / scale; char[] bar = new char[(int) (((double) value / (double) max) * barSize)]; Arrays.fill(bar, '='); String objectString = String.valueOf(cv.getValue()); diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java Wed May 28 21:17:16 2014 +0200 @@ -44,6 +44,15 @@ } } + public void add(Object value, long count) { + CountedValue cv = map.get(value); + if (cv == null) { + map.put(value, new CountedValue(count, value)); + } else { + cv.add(count); + } + } + @Override public String getName() { return name; diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java --- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java Wed May 28 21:17:16 2014 +0200 @@ -121,17 +121,4 @@ map.setAndGrow(newNode, 1); assertEquals((Integer) 1, map.get(newNode)); } - - @Test(expected = AssertionError.class) - public void testNewSetAndGrowMultiple() { - TestNode newNode = graph.add(new TestNode()); - map.setAndGrow(newNode, 1); - assertEquals((Integer) 1, map.get(newNode)); - /* - * Failing here is not required, but if this behavior changes, usages of getAndGrow and - * setAndGrow need to be checked for compatibility. - */ - TestNode newNode2 = graph.add(new TestNode()); - map.get(newNode2); - } } diff -r 42eaa579e134 -r 5d0fbc245e55 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 Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Wed May 28 21:17:16 2014 +0200 @@ -740,11 +740,7 @@ } public NodeBitMap createNodeBitMap() { - return createNodeBitMap(false); - } - - public NodeBitMap createNodeBitMap(boolean autoGrow) { - return new NodeBitMap(this, autoGrow); + return new NodeBitMap(this); } public NodeMap createNodeMap() { @@ -756,11 +752,11 @@ } public NodeWorkList createNodeWorkList() { - return new NodeWorkList(this); + return new NodeWorkList.SingletonNodeWorkList(this); } - public NodeWorkList createNodeWorkList(boolean fill, int iterationLimitPerNode) { - return new NodeWorkList(this, fill, iterationLimitPerNode); + public NodeWorkList createIterativeNodeWorkList(boolean fill, int iterationLimitPerNode) { + return new NodeWorkList.IterativeNodeWorkList(this, fill, iterationLimitPerNode); } void register(Node node) { diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java Wed May 28 21:17:16 2014 +0200 @@ -27,92 +27,109 @@ import com.oracle.graal.graph.iterators.*; public final class NodeBitMap implements NodeIterable { + private static final int SHIFT = 6; - private final boolean autoGrow; - private final BitSet bitMap; + private long[] bits; private int nodeCount; private final NodeIdAccessor nodeIdAccessor; public NodeBitMap(Graph graph) { - this(graph, false); + nodeCount = graph.nodeIdCount(); + bits = new long[sizeForNodeCount(nodeCount)]; + this.nodeIdAccessor = new NodeIdAccessor(graph); } - public NodeBitMap(Graph graph, boolean autoGrow) { - this(graph, autoGrow, graph.nodeIdCount(), new BitSet(graph.nodeIdCount())); + private static int sizeForNodeCount(int nodeCount) { + return (nodeCount + Long.SIZE - 1) >> SHIFT; } - private NodeBitMap(Graph graph, boolean autoGrow, int nodeCount, BitSet bits) { - this.nodeIdAccessor = new NodeIdAccessor(graph); - this.autoGrow = autoGrow; - this.nodeCount = nodeCount; - bitMap = bits; + private NodeBitMap(NodeBitMap other) { + this.bits = other.bits.clone(); + this.nodeCount = other.nodeCount; + this.nodeIdAccessor = other.nodeIdAccessor; } public Graph graph() { return nodeIdAccessor.getGraph(); } - public void setUnion(NodeBitMap other) { - bitMap.or(other.bitMap); - } - - public void negate() { - grow(); - bitMap.flip(0, nodeCount); - } - - public boolean isNotNewMarked(Node node) { - return !isNew(node) && isMarked(node); - } - - public boolean isNotNewNotMarked(Node node) { - return !isNew(node) && !isMarked(node); - } - - public boolean isMarked(Node node) { - return bitMap.get(nodeIdAccessor.getNodeId(node)); - } - public boolean isNew(Node node) { return nodeIdAccessor.getNodeId(node) >= nodeCount; } + public boolean isMarked(Node node) { + assert check(node, false); + int id = nodeIdAccessor.getNodeId(node); + return (bits[id >> SHIFT] & (1L << id)) != 0; + } + + public boolean isMarkedAndGrow(Node node) { + assert check(node, true); + int id = nodeIdAccessor.getNodeId(node); + checkGrow(id); + return (bits[id >> SHIFT] & (1L << id)) != 0; + } + public void mark(Node node) { - if (autoGrow && isNew(node)) { - grow(); - } - assert check(node); - bitMap.set(nodeIdAccessor.getNodeId(node)); + assert check(node, false); + int id = nodeIdAccessor.getNodeId(node); + bits[id >> SHIFT] |= (1L << id); + } + + public void markAndGrow(Node node) { + assert check(node, true); + int id = nodeIdAccessor.getNodeId(node); + checkGrow(id); + bits[id >> SHIFT] |= (1L << id); } public void clear(Node node) { - if (autoGrow && isNew(node)) { - return; + assert check(node, false); + int id = nodeIdAccessor.getNodeId(node); + bits[id >> SHIFT] &= ~(1L << id); + } + + public void clearAndGrow(Node node) { + assert check(node, true); + int id = nodeIdAccessor.getNodeId(node); + checkGrow(id); + bits[id >> SHIFT] &= ~(1L << id); + } + + private void checkGrow(int id) { + if (id >= nodeCount) { + if ((id >> SHIFT) >= bits.length) { + grow(); + } else { + nodeCount = id + 1; + } } - assert check(node); - bitMap.clear(nodeIdAccessor.getNodeId(node)); } public void clearAll() { - bitMap.clear(); + Arrays.fill(bits, 0); } public void intersect(NodeBitMap other) { assert graph() == other.graph(); - bitMap.and(other.bitMap); - } - - public void grow(Node node) { - nodeCount = Math.max(nodeCount, nodeIdAccessor.getNodeId(node) + 1); + int commonLength = Math.min(bits.length, other.bits.length); + for (int i = commonLength; i < bits.length; i++) { + bits[i] = 0; + } + for (int i = 0; i < commonLength; i++) { + bits[i] &= other.bits[i]; + } } - public void grow() { + private void grow() { nodeCount = Math.max(nodeCount, graph().nodeIdCount()); + int newLength = Math.max((bits.length * 3 / 2) + 1, sizeForNodeCount(nodeCount)); + bits = Arrays.copyOf(bits, newLength); } - private boolean check(Node node) { + private boolean check(Node node, boolean grow) { assert node.graph() == graph() : "this node is not part of the graph"; - assert !isNew(node) : "node was added to the graph after creating the node bitmap: " + node; + assert grow || !isNew(node) : "node was added to the graph after creating the node bitmap: " + node; assert node.isAlive() : "node is deleted!"; return true; } @@ -175,12 +192,8 @@ return new MarkedNodeIterator(NodeBitMap.this, graph().getNodes().iterator()); } - public int cardinality() { - return bitMap.cardinality(); - } - public NodeBitMap copy() { - return new NodeBitMap(graph(), autoGrow, nodeCount, (BitSet) bitMap.clone()); + return new NodeBitMap(this); } @Override @@ -190,7 +203,11 @@ @Override public int count() { - return bitMap.cardinality(); + int count = 0; + for (long l : bits) { + count += Long.bitCount(l); + } + return count; } @Override diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java Wed May 28 21:17:16 2014 +0200 @@ -28,6 +28,8 @@ public class NodeMap extends NodeIdAccessor { + private static final int MIN_REALLOC_SIZE = 16; + protected Object[] values; public NodeMap(Graph graph) { @@ -54,7 +56,7 @@ private void checkAndGrow(Node node) { if (isNew(node)) { - this.values = Arrays.copyOf(values, graph.nodeIdCount()); + this.values = Arrays.copyOf(values, Math.max(MIN_REALLOC_SIZE, graph.nodeIdCount() * 3 / 2)); } assert check(node); } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeWorkList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeWorkList.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeWorkList.java Wed May 28 21:17:16 2014 +0200 @@ -24,23 +24,11 @@ import java.util.*; -public class NodeWorkList implements Iterable { +public abstract class NodeWorkList implements Iterable { - private final NodeBitMap visited; - private final NodeBitMap inQueue; - private final Queue worklist; - private int iterationLimit = Integer.MAX_VALUE; - private Node firstNoChange; - private Node lastPull; - private Node lastChain; + protected final Queue worklist; - public NodeWorkList(Graph graph) { - this(graph, false, -1); - } - - public NodeWorkList(Graph graph, boolean fill, int iterationLimitPerNode) { - visited = graph.createNodeBitMap(); - inQueue = graph.createNodeBitMap(); + private NodeWorkList(Graph graph, boolean fill) { if (fill) { ArrayDeque deque = new ArrayDeque<>(graph.getNodeCount()); for (Node node : graph.getNodes()) { @@ -50,9 +38,6 @@ } else { worklist = new ArrayDeque<>(); } - if (iterationLimitPerNode > 0) { - iterationLimit = iterationLimitPerNode * graph.getNodeCount(); - } } public void addAll(Iterable nodes) { @@ -63,111 +48,13 @@ } } - public void add(Node node) { - if (node != null) { - if (visited.isNew(node)) { - visited.grow(node); - inQueue.grow(node); - } - if (!visited.isMarked(node)) { - addAgain(node); - } - } - } + public abstract void add(Node node); - public void addAgain(Node node) { - if (visited.isNew(node)) { - visited.grow(node); - inQueue.grow(node); - } - if (node != null && !inQueue.isMarked(node)) { - if (lastPull == node) { - if (firstNoChange == null) { - firstNoChange = node; - lastChain = node; - } else if (node == firstNoChange) { - throw new InfiniteWorkException("ReAdded " + node); - } else { - lastChain = node; - } - } else { - firstNoChange = null; - } - visited.mark(node); - inQueue.mark(node); - worklist.add(node); - } - } - - public void clearVisited() { - visited.clearAll(); - } - - public void replaced(Node newNode, Node oldNode) { - this.replaced(newNode, oldNode, false); - } + private abstract class QueueConsumingIterator implements Iterator { - public void replaced(Node newNode, Node oldNode, boolean add) { - worklist.remove(oldNode); - if (newNode == null) { - return; - } - if (add) { - this.add(newNode); - } - for (Node n : newNode.usages()) { - addAgain(n); - } - } - - public boolean isMarked(Node node) { - return visited.isMarked(node); - } - - public boolean isNew(Node node) { - return visited.isNew(node); - } - - public boolean isEmpty() { - return worklist.isEmpty(); - } - - public boolean isInQueue(Node node) { - return !inQueue.isNew(node) && inQueue.isMarked(node); - } - - private class QueueConsumingIterator implements Iterator { - - private final Queue queue; - - public QueueConsumingIterator(Queue queue) { - this.queue = queue; - } - - @Override - public boolean hasNext() { - dropDeleted(); - return iterationLimit > 0 && !queue.isEmpty(); - } - - @Override - public Node next() { - if (iterationLimit-- <= 0) { - throw new NoSuchElementException(); - } - dropDeleted(); - Node node = queue.remove(); - if (lastPull != lastChain) { - firstNoChange = null; - } - lastPull = node; - inQueue.clear(node); - return node; - } - - private void dropDeleted() { - while (!queue.isEmpty() && queue.peek().isDeleted()) { - queue.remove(); + protected void dropDeleted() { + while (!worklist.isEmpty() && worklist.peek().isDeleted()) { + worklist.remove(); } } @@ -177,74 +64,142 @@ } } - @Override - public Iterator iterator() { - return new QueueConsumingIterator(worklist); - } - - private static class UnmarkedNodeIterator implements Iterator { + public static final class IterativeNodeWorkList extends NodeWorkList { - private final NodeBitMap visited; - private Iterator nodes; - private Node nextNode; - - public UnmarkedNodeIterator(NodeBitMap visited, Iterator nodes) { - this.visited = visited; - this.nodes = nodes; - forward(); - } + private static final int EXPLICIT_BITMAP_THRESHOLD = 10; + protected NodeBitMap inQueue; - private void forward() { - do { - if (!nodes.hasNext()) { - nextNode = null; - return; - } - nextNode = nodes.next(); - } while (visited.isMarked(nextNode)); - } + private int iterationLimit = Integer.MAX_VALUE; + private Node firstNoChange; + private Node lastPull; + private Node lastChain; - @Override - public boolean hasNext() { - return nextNode != null; - } - - @Override - public Node next() { - try { - return nextNode; - } finally { - forward(); + public IterativeNodeWorkList(Graph graph, boolean fill, int iterationLimitPerNode) { + super(graph, fill); + if (iterationLimitPerNode > 0) { + iterationLimit = iterationLimitPerNode * graph.getNodeCount(); } } @Override - public void remove() { - throw new UnsupportedOperationException(); + public Iterator iterator() { + return new QueueConsumingIterator() { + @Override + public boolean hasNext() { + dropDeleted(); + return iterationLimit > 0 && !worklist.isEmpty(); + } + + @Override + public Node next() { + if (iterationLimit-- <= 0) { + throw new NoSuchElementException(); + } + dropDeleted(); + Node node = worklist.remove(); + assert updateInfiniteWork(node); + if (inQueue != null) { + inQueue.clearAndGrow(node); + } + return node; + } + + private boolean updateInfiniteWork(Node node) { + if (lastPull != lastChain) { + firstNoChange = null; + } + lastPull = node; + return true; + } + }; } + @Override + public void add(Node node) { + if (node != null) { + if (inQueue != null) { + if (inQueue.isMarkedAndGrow(node)) { + return; + } + } else { + if (worklist.size() > EXPLICIT_BITMAP_THRESHOLD) { + inflateToBitMap(node.graph()); + } else { + for (Node queuedNode : worklist) { + if (queuedNode == node) { + return; + } + } + } + } + assert checkInfiniteWork(node) : "Readded " + node; + if (inQueue != null) { + inQueue.markAndGrow(node); + } + worklist.add(node); + } + } + + private boolean checkInfiniteWork(Node node) { + if (lastPull == node) { + if (firstNoChange == null) { + firstNoChange = node; + lastChain = node; + } else if (node == firstNoChange) { + return false; + } else { + lastChain = node; + } + } else { + firstNoChange = null; + } + return true; + } + + private void inflateToBitMap(Graph graph) { + assert inQueue == null; + inQueue = graph.createNodeBitMap(); + for (Node queuedNode : worklist) { + if (queuedNode.isAlive()) { + inQueue.mark(queuedNode); + } + } + } } - public Iterable unmarkedNodes() { - return new Iterable() { + public static final class SingletonNodeWorkList extends NodeWorkList { + protected final NodeBitMap visited; - @Override - public Iterator iterator() { - return new UnmarkedNodeIterator(visited, visited.graph().getNodes().iterator()); - } - }; - } - - public static class InfiniteWorkException extends RuntimeException { - - private static final long serialVersionUID = -5319329402219396658L; - - public InfiniteWorkException() { - super(); + public SingletonNodeWorkList(Graph graph) { + super(graph, false); + visited = graph.createNodeBitMap(); } - public InfiniteWorkException(String message) { - super(message); + @Override + public void add(Node node) { + if (node != null) { + if (!visited.isMarkedAndGrow(node)) { + visited.mark(node); + worklist.add(node); + } + } + } + + @Override + public Iterator iterator() { + return new QueueConsumingIterator() { + @Override + public boolean hasNext() { + dropDeleted(); + return !worklist.isEmpty(); + } + + @Override + public Node next() { + dropDeleted(); + return worklist.remove(); + } + }; } } } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctPredicatedProxyNodeIterator.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctPredicatedProxyNodeIterator.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctPredicatedProxyNodeIterator.java Wed May 28 21:17:16 2014 +0200 @@ -50,7 +50,7 @@ return true; } if (visited == null) { - visited = n.graph().createNodeBitMap(true); + visited = n.graph().createNodeBitMap(); } boolean accept = !visited.isMarked(n); visited.mark(n); diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Wed May 28 21:17:16 2014 +0200 @@ -23,15 +23,18 @@ package com.oracle.graal.hotspot.test; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; + import java.lang.ref.*; import java.lang.reflect.*; import com.oracle.graal.phases.common.inlining.policy.InlineEverythingPolicy; + import org.junit.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; @@ -160,7 +163,7 @@ } public static Object test5Snippet() throws Exception { - return UnsafeLoadNode.load(wr, useCompressedOops() ? 12 : 16, Kind.Object, LocationIdentity.ANY_LOCATION); + return UnsafeAccess.unsafe.getObject(wr, useCompressedOops() ? 12L : 16L); } /** diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Wed May 28 21:17:16 2014 +0200 @@ -216,23 +216,29 @@ // Canonicalization may attempt to process an unsafe read before // processing a guard (e.g. a null check or a type check) for this read // so we need to check the object being read - if (object != null && isInObject(object)) { + if (object != null) { if (isFinal()) { - Constant value = readValue(receiver); - if (assumeNonStaticFinalFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) { - return value; + if (isInObject(object)) { + Constant value = readValue(receiver); + if (assumeNonStaticFinalFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) { + return value; + } } } else if (isStable()) { - Constant value = readValue(receiver); - if (assumeDefaultStableFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) { - return value; + if (isInObject(object)) { + Constant value = readValue(receiver); + if (assumeDefaultStableFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) { + return value; + } } } else { Class clazz = object.getClass(); if (StableOptionValue.class.isAssignableFrom(clazz)) { - assert getName().equals("value") : "Unexpected field in " + StableOptionValue.class.getName() + " hierarchy:" + this; - StableOptionValue option = (StableOptionValue) object; - return HotSpotObjectConstant.forObject(option.getValue()); + if (isInObject(object)) { + assert getName().equals("value") : "Unexpected field in " + StableOptionValue.class.getName() + " hierarchy:" + this; + StableOptionValue option = (StableOptionValue) object; + return HotSpotObjectConstant.forObject(option.getValue()); + } } } } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Wed May 28 21:17:16 2014 +0200 @@ -66,7 +66,7 @@ } public boolean contains(Node n) { - return nodes().contains(n); + return nodes().isMarkedAndGrow(n); } @SuppressWarnings("unchecked") @@ -96,7 +96,7 @@ return original; } - public abstract NodeIterable nodes(); + public abstract NodeBitMap nodes(); public StructuredGraph graph() { LoopEx l; @@ -155,7 +155,7 @@ } protected static NodeBitMap computeNodes(Graph graph, Iterable blocks, Iterable earlyExits) { - final NodeBitMap nodes = graph.createNodeBitMap(true); + final NodeBitMap nodes = graph.createNodeBitMap(); for (BeginNode b : blocks) { if (b.isDeleted()) { continue; @@ -187,7 +187,7 @@ } } - final NodeBitMap notloopNodes = graph.createNodeBitMap(true); + final NodeBitMap notloopNodes = graph.createNodeBitMap(); for (BeginNode b : blocks) { if (b.isDeleted()) { continue; @@ -336,8 +336,8 @@ * * We now update the original fragment's nodes accordingly: */ - state.applyToVirtual(node -> original.nodes.clear(node)); - exitState.applyToVirtual(node -> original.nodes.mark(node)); + state.applyToVirtual(node -> original.nodes.clearAndGrow(node)); + exitState.applyToVirtual(node -> original.nodes.markAndGrow(node)); } FrameState finalExitState = exitState; diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Wed May 28 21:17:16 2014 +0200 @@ -102,7 +102,7 @@ } @Override - public NodeIterable nodes() { + public NodeBitMap nodes() { if (nodes == null) { LoopFragmentWhole whole = loop().whole(); whole.nodes(); // init nodes bitmap in whole @@ -203,10 +203,10 @@ for (LoopExitNode exit : exits()) { FrameState exitState = exit.stateAfter(); if (exitState != null) { - exitState.applyToVirtual(v -> usagesToPatch.mark(v)); + exitState.applyToVirtual(v -> usagesToPatch.markAndGrow(v)); } for (ProxyNode proxy : exit.proxies()) { - usagesToPatch.mark(proxy); + usagesToPatch.markAndGrow(proxy); } } @@ -232,7 +232,7 @@ newPhis.add(newPhi); for (Node usage : phi.usages().snapshot()) { // patch only usages that should use the new phi ie usages that were peeled - if (usagesToPatch.isMarked(usage)) { + if (usagesToPatch.isMarkedAndGrow(usage)) { usage.replaceFirstInput(phi, newPhi); } } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInsideBefore.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInsideBefore.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInsideBefore.java Wed May 28 21:17:16 2014 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.loop; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; public class LoopFragmentInsideBefore extends LoopFragmentInside { @@ -51,8 +50,7 @@ } @Override - public NodeIterable nodes() { - // TODO Auto-generated method stub + public NodeBitMap nodes() { return null; } } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInsideFrom.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInsideFrom.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInsideFrom.java Wed May 28 21:17:16 2014 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.loop; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; public class LoopFragmentInsideFrom extends LoopFragmentInside { @@ -51,8 +50,7 @@ } @Override - public NodeIterable nodes() { - // TODO Auto-generated method stub + public NodeBitMap nodes() { return null; } } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java Wed May 28 21:17:16 2014 +0200 @@ -25,7 +25,6 @@ import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Graph.DuplicationReplacement; -import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; @@ -55,7 +54,7 @@ } @Override - public NodeIterable nodes() { + public NodeBitMap nodes() { if (nodes == null) { Loop lirLoop = loop().lirLoop(); nodes = LoopFragment.computeNodes(graph(), LoopFragment.toHirBlocks(lirLoop.getBlocks()), LoopFragment.toHirExits(lirLoop.getExits())); diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Wed May 28 21:17:16 2014 +0200 @@ -72,7 +72,7 @@ for (Node successor : controlSplit.successors()) { BeginNode branch = (BeginNode) successor; // this may count twice because of fall-through in switches - inBranchTotal += loop.nodesInLoopFrom(branch, postDom).cardinality(); + inBranchTotal += loop.nodesInLoopFrom(branch, postDom).count(); double probability = controlSplit.probability(branch); if (probability > maxProbability) { maxProbability = probability; diff -r 42eaa579e134 -r 5d0fbc245e55 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 Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Wed May 28 21:17:16 2014 +0200 @@ -149,65 +149,27 @@ LogicNegationNode negation = (LogicNegationNode) condition(); IfNode newIfNode = graph().add(new IfNode(negation.getInput(), falseSucc, trueSucc, 1 - trueSuccessorProbability)); predecessor().replaceFirstSuccessor(this, newIfNode); - this.safeDelete(); + GraphUtil.killWithUnusedFloatingInputs(this); return; } - if (trueSuccessor().usages().isEmpty() && falseSuccessor().usages().isEmpty()) { - // push similar nodes upwards through the if, thereby deduplicating them - do { - BeginNode trueSucc = trueSuccessor(); - BeginNode falseSucc = falseSuccessor(); - if (trueSucc.getClass() == BeginNode.class && falseSucc.getClass() == BeginNode.class && trueSucc.next() instanceof FixedWithNextNode && falseSucc.next() instanceof FixedWithNextNode) { - FixedWithNextNode trueNext = (FixedWithNextNode) trueSucc.next(); - FixedWithNextNode falseNext = (FixedWithNextNode) falseSucc.next(); - NodeClass nodeClass = trueNext.getNodeClass(); - if (trueNext.getClass() == falseNext.getClass()) { - if (nodeClass.inputsEqual(trueNext, falseNext) && nodeClass.valueEqual(trueNext, falseNext)) { - falseNext.replaceAtUsages(trueNext); - graph().removeFixed(falseNext); - FixedNode next = trueNext.next(); - trueNext.setNext(null); - trueNext.replaceAtPredecessor(next); - graph().addBeforeFixed(this, trueNext); - for (Node usage : trueNext.usages().snapshot()) { - if (usage.getNodeClass().valueNumberable() && !usage.getNodeClass().isLeafNode()) { - Node newNode = graph().findDuplicate(usage); - if (newNode != null) { - usage.replaceAtUsages(newNode); - usage.safeDelete(); - } - } - if (usage.isAlive()) { - tool.addToWorkList(usage); - } - } - continue; - } - } - } - } while (false); - } - - if (checkForUnsignedCompare(tool)) { - return; - } - if (condition() instanceof LogicConstantNode) { LogicConstantNode c = (LogicConstantNode) condition(); if (c.getValue()) { tool.deleteBranch(falseSuccessor()); tool.addToWorkList(trueSuccessor()); graph().removeSplit(this, trueSuccessor()); - return; } else { tool.deleteBranch(trueSuccessor()); tool.addToWorkList(falseSuccessor()); graph().removeSplit(this, falseSuccessor()); - return; } - } else if (trueSuccessor().usages().isEmpty() && falseSuccessor().usages().isEmpty()) { + return; + } + if (trueSuccessor().usages().isEmpty() && falseSuccessor().usages().isEmpty()) { - if (removeOrMaterializeIf(tool)) { + pushNodesThroughIf(tool); + + if (checkForUnsignedCompare(tool) || removeOrMaterializeIf(tool)) { return; } } @@ -248,6 +210,43 @@ } } + private void pushNodesThroughIf(SimplifierTool tool) { + assert trueSuccessor().usages().isEmpty() && falseSuccessor().usages().isEmpty(); + // push similar nodes upwards through the if, thereby deduplicating them + do { + BeginNode trueSucc = trueSuccessor(); + BeginNode falseSucc = falseSuccessor(); + if (trueSucc.getClass() == BeginNode.class && falseSucc.getClass() == BeginNode.class && trueSucc.next() instanceof FixedWithNextNode && falseSucc.next() instanceof FixedWithNextNode) { + FixedWithNextNode trueNext = (FixedWithNextNode) trueSucc.next(); + FixedWithNextNode falseNext = (FixedWithNextNode) falseSucc.next(); + NodeClass nodeClass = trueNext.getNodeClass(); + if (trueNext.getClass() == falseNext.getClass()) { + if (nodeClass.inputsEqual(trueNext, falseNext) && nodeClass.valueEqual(trueNext, falseNext)) { + falseNext.replaceAtUsages(trueNext); + graph().removeFixed(falseNext); + FixedNode next = trueNext.next(); + trueNext.setNext(null); + trueNext.replaceAtPredecessor(next); + graph().addBeforeFixed(this, trueNext); + for (Node usage : trueNext.usages().snapshot()) { + if (usage.getNodeClass().valueNumberable() && !usage.getNodeClass().isLeafNode()) { + Node newNode = graph().findDuplicate(usage); + if (newNode != null) { + usage.replaceAtUsages(newNode); + usage.safeDelete(); + } + } + if (usage.isAlive()) { + tool.addToWorkList(usage); + } + } + continue; + } + } + } + } while (false); + } + /** * Recognize a couple patterns that can be merged into an unsigned compare. * @@ -255,7 +254,8 @@ * @return true if a replacement was done. */ private boolean checkForUnsignedCompare(SimplifierTool tool) { - if (condition() instanceof IntegerLessThanNode && trueSuccessor().usages().isEmpty() && falseSuccessor().usages().isEmpty()) { + assert trueSuccessor().usages().isEmpty() && falseSuccessor().usages().isEmpty(); + if (condition() instanceof IntegerLessThanNode) { IntegerLessThanNode lessThan = (IntegerLessThanNode) condition(); Constant y = lessThan.y().stamp().asConstant(); if (y != null && y.asLong() == 0 && falseSuccessor().next() instanceof IfNode) { @@ -478,6 +478,7 @@ * @return true if a transformation was made, false otherwise */ private boolean removeOrMaterializeIf(SimplifierTool tool) { + assert trueSuccessor().usages().isEmpty() && falseSuccessor().usages().isEmpty(); if (trueSuccessor().next() instanceof AbstractEndNode && falseSuccessor().next() instanceof AbstractEndNode) { AbstractEndNode trueEnd = (AbstractEndNode) trueSuccessor().next(); AbstractEndNode falseEnd = (AbstractEndNode) falseSuccessor().next(); @@ -621,6 +622,11 @@ * @return true if a transformation was made, false otherwise */ private boolean removeIntermediateMaterialization(SimplifierTool tool) { + if (!(predecessor() instanceof MergeNode) || predecessor() instanceof LoopBeginNode) { + return false; + } + MergeNode merge = (MergeNode) predecessor(); + if (!(condition() instanceof CompareNode)) { return false; } @@ -630,16 +636,6 @@ return false; } - if (!(predecessor() instanceof MergeNode)) { - return false; - } - - if (predecessor() instanceof LoopBeginNode) { - return false; - } - - MergeNode merge = (MergeNode) predecessor(); - // Only consider merges with a single usage that is both a phi and an operand of the // comparison NodeIterable mergeUsages = merge.usages(); diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Wed May 28 21:17:16 2014 +0200 @@ -26,6 +26,8 @@ import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.internal.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; @@ -62,6 +64,17 @@ */ public abstract boolean unorderedIsTrue(); + protected static final DebugHistogram histogram = Debug.createHistogram("histo"); + + static { + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + new DebugHistogramAsciiPrinter(System.out).print(histogram); + } + }); + } + private LogicNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, ConstantReflectionProvider constantReflection, Condition cond) { Constant trueConstant = conditionalNode.trueValue().asConstant(); Constant falseConstant = conditionalNode.falseValue().asConstant(); @@ -105,38 +118,42 @@ return result; } if (x().isConstant()) { - if (y() instanceof ConditionalNode) { - return optimizeConditional(x().asConstant(), (ConditionalNode) y(), tool.getConstantReflection(), condition().mirror()); - } else if (y() instanceof NormalizeCompareNode) { - return optimizeNormalizeCmp(x().asConstant(), (NormalizeCompareNode) y(), true); + if ((result = canonicalizeSymmetricConstant(tool, x().asConstant(), y(), true)) != this) { + return result; } } else if (y().isConstant()) { - if (x() instanceof ConditionalNode) { - return optimizeConditional(y().asConstant(), (ConditionalNode) x(), tool.getConstantReflection(), condition()); - } else if (x() instanceof NormalizeCompareNode) { - return optimizeNormalizeCmp(y().asConstant(), (NormalizeCompareNode) x(), false); + if ((result = canonicalizeSymmetricConstant(tool, y().asConstant(), x(), false)) != this) { + return result; } - } - if (x() instanceof ConvertNode && y() instanceof ConvertNode) { + } else if (x() instanceof ConvertNode && y() instanceof ConvertNode) { ConvertNode convertX = (ConvertNode) x(); ConvertNode convertY = (ConvertNode) y(); if (convertX.preservesOrder(condition()) && convertY.preservesOrder(condition()) && convertX.getInput().stamp().isCompatible(convertY.getInput().stamp())) { - setX(convertX.getInput()); - setY(convertY.getInput()); + return graph().unique(duplicateModified(convertX.getInput(), convertY.getInput())); } - } else if (x() instanceof ConvertNode && y().isConstant()) { - ConvertNode convertX = (ConvertNode) x(); - ConstantNode newY = canonicalConvertConstant(tool, convertX, y().asConstant()); - if (newY != null) { - setX(convertX.getInput()); - setY(newY); + + } + return this; + } + + protected abstract CompareNode duplicateModified(ValueNode newX, ValueNode newY); + + protected Node canonicalizeSymmetricConstant(CanonicalizerTool tool, Constant constant, ValueNode nonConstant, boolean mirrored) { + if (nonConstant instanceof BinaryNode) { + if (nonConstant instanceof ConditionalNode) { + return optimizeConditional(constant, (ConditionalNode) nonConstant, tool.getConstantReflection(), mirrored ? condition().mirror() : condition()); + } else if (nonConstant instanceof NormalizeCompareNode) { + return optimizeNormalizeCmp(constant, (NormalizeCompareNode) nonConstant, mirrored); } - } else if (y() instanceof ConvertNode && x().isConstant()) { - ConvertNode convertY = (ConvertNode) y(); - ConstantNode newX = canonicalConvertConstant(tool, convertY, x().asConstant()); - if (newX != null) { - setX(newX); - setY(convertY.getInput()); + } else if (nonConstant instanceof ConvertNode) { + ConvertNode convert = (ConvertNode) nonConstant; + ConstantNode newConstant = canonicalConvertConstant(tool, convert, constant); + if (newConstant != null) { + if (mirrored) { + return graph().unique(duplicateModified(newConstant, convert.getInput())); + } else { + return graph().unique(duplicateModified(convert.getInput(), newConstant)); + } } } return this; diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Wed May 28 21:17:16 2014 +0200 @@ -68,4 +68,9 @@ } return super.evaluate(constantReflection, forX, forY); } + + @Override + protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { + return new FloatEqualsNode(newX, newY); + } } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java Wed May 28 21:17:16 2014 +0200 @@ -67,4 +67,9 @@ } return super.evaluate(constantReflection, forX, forY); } + + @Override + protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { + return new FloatLessThanNode(newX, newY, unorderedIsTrue); + } } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java Wed May 28 21:17:16 2014 +0200 @@ -86,4 +86,9 @@ } return this; } + + @Override + protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { + return new IntegerBelowThanNode(newX, newY); + } } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Wed May 28 21:17:16 2014 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ProfilingInfo.*; +import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -72,6 +72,11 @@ } @Override + protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { + return new IntegerEqualsNode(newX, newY); + } + + @Override public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { return TriState.TRUE; @@ -82,62 +87,51 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - Node result = super.canonical(tool); - if (result != this) { - return result; - } - - result = canonicalizeSymmetric(x(), y()); - if (result != this) { - return result; - } - - return canonicalizeSymmetric(y(), x()); - } - - private ValueNode canonicalizeSymmetric(ValueNode x, ValueNode y) { - if (y.isConstant() && y.asConstant().asLong() == 0) { - if (x instanceof AndNode) { - return graph().unique(new IntegerTestNode(((AndNode) x).x(), ((AndNode) x).y())); - } else if (x instanceof LeftShiftNode) { - LeftShiftNode shift = (LeftShiftNode) x; - if (shift.y().isConstant()) { - int mask = shift.getShiftAmountMask(); - int amount = shift.y().asConstant().asInt() & mask; - if (shift.x().getKind() == Kind.Int) { - return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 >>> amount, graph()))); - } else { - assert shift.x().getKind() == Kind.Long; - return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L >>> amount, graph()))); + protected Node canonicalizeSymmetricConstant(CanonicalizerTool tool, Constant constant, ValueNode nonConstant, boolean mirrored) { + if (constant.asLong() == 0) { + if (nonConstant instanceof AndNode) { + AndNode andNode = (AndNode) nonConstant; + return graph().unique(new IntegerTestNode(andNode.x(), andNode.y())); + } else if (nonConstant instanceof ShiftNode) { + if (nonConstant instanceof LeftShiftNode) { + LeftShiftNode shift = (LeftShiftNode) nonConstant; + if (shift.y().isConstant()) { + int mask = shift.getShiftAmountMask(); + int amount = shift.y().asConstant().asInt() & mask; + if (shift.x().getKind() == Kind.Int) { + return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 >>> amount, graph()))); + } else { + assert shift.x().getKind() == Kind.Long; + return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L >>> amount, graph()))); + } } - } - } else if (x instanceof RightShiftNode) { - RightShiftNode shift = (RightShiftNode) x; - if (shift.y().isConstant() && ((IntegerStamp) shift.x().stamp()).isPositive()) { - int mask = shift.getShiftAmountMask(); - int amount = shift.y().asConstant().asInt() & mask; - if (shift.x().getKind() == Kind.Int) { - return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 << amount, graph()))); - } else { - assert shift.x().getKind() == Kind.Long; - return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L << amount, graph()))); + } else if (nonConstant instanceof RightShiftNode) { + RightShiftNode shift = (RightShiftNode) nonConstant; + if (shift.y().isConstant() && ((IntegerStamp) shift.x().stamp()).isPositive()) { + int mask = shift.getShiftAmountMask(); + int amount = shift.y().asConstant().asInt() & mask; + if (shift.x().getKind() == Kind.Int) { + return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 << amount, graph()))); + } else { + assert shift.x().getKind() == Kind.Long; + return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L << amount, graph()))); + } } - } - } else if (x instanceof UnsignedRightShiftNode) { - UnsignedRightShiftNode shift = (UnsignedRightShiftNode) x; - if (shift.y().isConstant()) { - int mask = shift.getShiftAmountMask(); - int amount = shift.y().asConstant().asInt() & mask; - if (shift.x().getKind() == Kind.Int) { - return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 << amount, graph()))); - } else { - assert shift.x().getKind() == Kind.Long; - return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L << amount, graph()))); + } else if (nonConstant instanceof UnsignedRightShiftNode) { + UnsignedRightShiftNode shift = (UnsignedRightShiftNode) nonConstant; + if (shift.y().isConstant()) { + int mask = shift.getShiftAmountMask(); + int amount = shift.y().asConstant().asInt() & mask; + if (shift.x().getKind() == Kind.Int) { + return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 << amount, graph()))); + } else { + assert shift.x().getKind() == Kind.Long; + return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L << amount, graph()))); + } } } } } - return this; + return super.canonicalizeSymmetricConstant(tool, constant, nonConstant, mirrored); } } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Wed May 28 21:17:16 2014 +0200 @@ -101,4 +101,9 @@ } return this; } + + @Override + protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { + return new IntegerLessThanNode(newX, newY); + } } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Wed May 28 21:17:16 2014 +0200 @@ -119,7 +119,7 @@ /* * One of the two objects has identity, the other doesn't. In code, this looks like * "Integer.valueOf(a) == new Integer(b)", which is always false. - * + * * In other words: an object created via valueOf can never be equal to one created * by new in the same compilation unit. */ @@ -138,4 +138,9 @@ } } } + + @Override + protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { + return new ObjectEqualsNode(newX, newY); + } } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Wed May 28 21:17:16 2014 +0200 @@ -42,6 +42,8 @@ private ResolvedJavaMethod targetMethod; private InvokeKind invokeKind; + private transient Stamp lastCanonicalizedReceiverStamp; + /** * @param arguments */ @@ -138,12 +140,17 @@ } // check if the type of the receiver can narrow the result - ValueNode receiver = receiver(); - ResolvedJavaType type = StampTool.typeOrNull(receiver); + Stamp receiverStamp = receiver().stamp(); + if (receiverStamp.equals(lastCanonicalizedReceiverStamp)) { + return this; + } + lastCanonicalizedReceiverStamp = receiverStamp; + + ResolvedJavaType type = StampTool.typeOrNull(receiverStamp); if (type != null && (invoke().stateAfter() != null || invoke().stateDuring() != null)) { // either the holder class is exact, or the receiver object has an exact type ResolvedJavaMethod resolvedMethod = type.resolveMethod(targetMethod, invoke().getContextType()); - if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver))) { + if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiverStamp))) { invokeKind = InvokeKind.Special; targetMethod = resolvedMethod; return this; diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Wed May 28 21:17:16 2014 +0200 @@ -137,9 +137,9 @@ protected void run(StructuredGraph graph) { boolean wholeGraph = newNodesMark == null || newNodesMark.isStart(); if (initWorkingSet == null) { - workList = graph.createNodeWorkList(wholeGraph, MAX_ITERATION_PER_NODE); + workList = graph.createIterativeNodeWorkList(wholeGraph, MAX_ITERATION_PER_NODE); } else { - workList = graph.createNodeWorkList(false, MAX_ITERATION_PER_NODE); + workList = graph.createIterativeNodeWorkList(false, MAX_ITERATION_PER_NODE); workList.addAll(initWorkingSet); } if (!wholeGraph) { @@ -154,7 +154,7 @@ @Override public void nodeChanged(Node node) { - workList.addAgain(node); + workList.add(node); } }; graph.trackInputChange(nodeChangedListener); @@ -336,7 +336,7 @@ if (node.inferStamp()) { METRIC_STAMP_CHANGED.increment(); for (Node usage : node.usages()) { - workList.addAgain(usage); + workList.add(usage); } return true; } @@ -373,7 +373,7 @@ @Override public void addToWorkList(Node node) { - workList.addAgain(node); + workList.add(node); } @Override diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Wed May 28 21:17:16 2014 +0200 @@ -145,8 +145,7 @@ } else { GuardNode newGuard = graph.unique(new GuardNode(condition, guardAnchor, deoptReason, action, negated, Constant.NULL_OBJECT)); if (OptEliminateGuards.getValue()) { - activeGuards.grow(); - activeGuards.mark(newGuard); + activeGuards.markAndGrow(newGuard); } return newGuard; } @@ -283,7 +282,7 @@ if (parentAnchor == null && OptEliminateGuards.getValue()) { for (GuardNode guard : anchor.asNode().usages().filter(GuardNode.class)) { - if (activeGuards.contains(guard)) { + if (activeGuards.isMarkedAndGrow(guard)) { activeGuards.clear(guard); } } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Wed May 28 21:17:16 2014 +0200 @@ -22,13 +22,13 @@ */ package com.oracle.graal.phases.common.inlining.info; +import java.util.*; + import com.oracle.graal.api.code.Assumptions; import com.oracle.graal.api.meta.ResolvedJavaMethod; -import com.oracle.graal.nodes.FixedWithNextNode; -import com.oracle.graal.nodes.Invoke; -import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.inlining.InliningUtil; - import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; import com.oracle.graal.phases.common.inlining.info.elem.InlineableMacroNode; import com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph; @@ -51,18 +51,33 @@ return invoke; } - protected static void inline(Invoke invoke, ResolvedJavaMethod concrete, Inlineable inlineable, Assumptions assumptions, boolean receiverNullCheck) { + protected static Collection inline(Invoke invoke, ResolvedJavaMethod concrete, Inlineable inlineable, Assumptions assumptions, boolean receiverNullCheck) { + Collection parameterUsages = new ArrayList<>(); if (inlineable instanceof InlineableGraph) { StructuredGraph calleeGraph = ((InlineableGraph) inlineable).getGraph(); - InliningUtil.inline(invoke, calleeGraph, receiverNullCheck); + Map duplicateMap = InliningUtil.inline(invoke, calleeGraph, receiverNullCheck); + getInlinedParameterUsages(parameterUsages, calleeGraph, duplicateMap); } else { assert inlineable instanceof InlineableMacroNode; Class macroNodeClass = ((InlineableMacroNode) inlineable).getMacroNodeClass(); - InliningUtil.inlineMacroNode(invoke, concrete, macroNodeClass); + FixedWithNextNode macroNode = InliningUtil.inlineMacroNode(invoke, concrete, macroNodeClass); + parameterUsages.add(macroNode); } InliningUtil.InlinedBytecodes.add(concrete.getCodeSize()); assumptions.recordMethodContents(concrete); + return parameterUsages; + } + + public static void getInlinedParameterUsages(Collection parameterUsages, StructuredGraph calleeGraph, Map duplicateMap) { + for (ParameterNode parameter : calleeGraph.getNodes(ParameterNode.class)) { + for (Node usage : parameter.usages()) { + Node node = duplicateMap.get(usage); + if (node != null && node.isAlive()) { + parameterUsages.add(node); + } + } + } } } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AssumptionInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AssumptionInlineInfo.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AssumptionInlineInfo.java Wed May 28 21:17:16 2014 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.phases.common.inlining.info; +import java.util.*; + import com.oracle.graal.api.code.Assumptions; import com.oracle.graal.api.meta.MetaAccessProvider; import com.oracle.graal.api.meta.MetaUtil; @@ -30,6 +32,7 @@ import com.oracle.graal.phases.common.inlining.InliningUtil; import com.oracle.graal.phases.util.Providers; import com.oracle.graal.api.code.Assumptions.Assumption; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; /** @@ -46,9 +49,9 @@ } @Override - public void inline(Providers providers, Assumptions assumptions) { + public Collection inline(Providers providers, Assumptions assumptions) { assumptions.record(takenAssumption); - super.inline(providers, assumptions); + return super.inline(providers, assumptions); } @Override diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/ExactInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/ExactInlineInfo.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/ExactInlineInfo.java Wed May 28 21:17:16 2014 +0200 @@ -22,10 +22,13 @@ */ package com.oracle.graal.phases.common.inlining.info; +import java.util.*; + import com.oracle.graal.api.code.Assumptions; import com.oracle.graal.api.meta.MetaAccessProvider; import com.oracle.graal.api.meta.MetaUtil; import com.oracle.graal.api.meta.ResolvedJavaMethod; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.Invoke; import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; import com.oracle.graal.phases.util.Providers; @@ -51,8 +54,8 @@ } @Override - public void inline(Providers providers, Assumptions assumptions) { - inline(invoke, concrete, inlineableElement, assumptions, !suppressNullCheck); + public Collection inline(Providers providers, Assumptions assumptions) { + return inline(invoke, concrete, inlineableElement, assumptions, !suppressNullCheck); } @Override diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java Wed May 28 21:17:16 2014 +0200 @@ -22,9 +22,12 @@ */ package com.oracle.graal.phases.common.inlining.info; +import java.util.*; + import com.oracle.graal.api.code.Assumptions; import com.oracle.graal.api.meta.MetaAccessProvider; import com.oracle.graal.api.meta.ResolvedJavaMethod; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.Invoke; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; @@ -68,8 +71,10 @@ * Performs the inlining described by this object and returns the node that represents the * return value of the inlined method (or null for void methods and methods that have no * non-exceptional exit). + * + * @return a collection of nodes that need to be canonicalized after the inlining */ - void inline(Providers providers, Assumptions assumptions); + Collection inline(Providers providers, Assumptions assumptions); /** * Try to make the call static bindable to avoid interface and virtual method calls. diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Wed May 28 21:17:16 2014 +0200 @@ -132,11 +132,11 @@ } @Override - public void inline(Providers providers, Assumptions assumptions) { + public Collection inline(Providers providers, Assumptions assumptions) { if (hasSingleMethod()) { - inlineSingleMethod(graph(), providers.getMetaAccess(), assumptions); + return inlineSingleMethod(graph(), providers.getMetaAccess(), assumptions); } else { - inlineMultipleMethods(graph(), providers, assumptions); + return inlineMultipleMethods(graph(), providers, assumptions); } } @@ -157,7 +157,7 @@ return notRecordedTypeProbability > 0; } - private void inlineMultipleMethods(StructuredGraph graph, Providers providers, Assumptions assumptions) { + private Collection inlineMultipleMethods(StructuredGraph graph, Providers providers, Assumptions assumptions) { int numberOfMethods = concretes.size(); FixedNode continuation = invoke.next(); @@ -222,6 +222,8 @@ ArrayList replacementNodes = new ArrayList<>(); + Collection parameterUsages = new ArrayList<>(); + // do the actual inlining for every invoke for (int i = 0; i < numberOfMethods; i++) { BeginNode node = successors[i]; @@ -239,7 +241,7 @@ GuardedValueNode anchoredReceiver = InliningUtil.createAnchoredReceiver(graph, node, commonType, receiver, exact); invokeForInlining.callTarget().replaceFirstInput(receiver, anchoredReceiver); - inline(invokeForInlining, methodAt(i), inlineableElementAt(i), assumptions, false); + parameterUsages.addAll(inline(invokeForInlining, methodAt(i), inlineableElementAt(i), assumptions, false)); replacementNodes.add(anchoredReceiver); } @@ -272,6 +274,7 @@ TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacementNodes, phaseContext, canonicalizer); } } + return parameterUsages; } private int getTypeCount(int concreteMethodIndex) { @@ -307,7 +310,7 @@ return result; } - private void inlineSingleMethod(StructuredGraph graph, MetaAccessProvider metaAccess, Assumptions assumptions) { + private Collection inlineSingleMethod(StructuredGraph graph, MetaAccessProvider metaAccess, Assumptions assumptions) { assert concretes.size() == 1 && inlineableElements.length == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0; BeginNode calleeEntryNode = graph.add(new BeginNode()); @@ -318,7 +321,7 @@ calleeEntryNode.setNext(invoke.asNode()); - inline(invoke, methodAt(0), inlineableElementAt(0), assumptions, false); + return inline(invoke, methodAt(0), inlineableElementAt(0), assumptions, false); } private boolean createDispatchOnTypeBeforeInvoke(StructuredGraph graph, BeginNode[] successors, boolean invokeIsOnlySuccessor, MetaAccessProvider metaAccess) { diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java Wed May 28 21:17:16 2014 +0200 @@ -22,9 +22,12 @@ */ package com.oracle.graal.phases.common.inlining.info; +import java.util.*; + import com.oracle.graal.api.code.Assumptions; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.calc.Condition; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.CompareNode; import com.oracle.graal.nodes.extended.LoadHubNode; @@ -87,9 +90,9 @@ } @Override - public void inline(Providers providers, Assumptions assumptions) { + public Collection inline(Providers providers, Assumptions assumptions) { createGuard(graph(), providers.getMetaAccess()); - inline(invoke, concrete, inlineableElement, assumptions, false); + return inline(invoke, concrete, inlineableElement, assumptions, false); } @Override diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Wed May 28 21:17:16 2014 +0200 @@ -22,11 +22,13 @@ */ package com.oracle.graal.phases.common.inlining.info.elem; +import java.util.*; + import com.oracle.graal.api.meta.Constant; import com.oracle.graal.api.meta.ResolvedJavaMethod; import com.oracle.graal.compiler.common.type.Stamp; import com.oracle.graal.debug.Debug; -import com.oracle.graal.graph.NodeInputList; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.CanonicalizerPhase; import com.oracle.graal.phases.common.DeadCodeEliminationPhase; @@ -71,31 +73,34 @@ boolean callerHasMoreInformationAboutArguments = false; NodeInputList args = invoke.callTarget().arguments(); + ArrayList parameterUsages = new ArrayList<>(); for (ParameterNode param : newGraph.getNodes(ParameterNode.class).snapshot()) { ValueNode arg = args.get(param.index()); if (arg.isConstant()) { Constant constant = arg.asConstant(); newGraph.replaceFloating(param, ConstantNode.forConstant(constant, context.getMetaAccess(), newGraph)); callerHasMoreInformationAboutArguments = true; + param.usages().snapshotTo(parameterUsages); } else { Stamp joinedStamp = param.stamp().join(arg.stamp()); if (joinedStamp != null && !joinedStamp.equals(param.stamp())) { param.setStamp(joinedStamp); callerHasMoreInformationAboutArguments = true; + param.usages().snapshotTo(parameterUsages); } } } - if (!callerHasMoreInformationAboutArguments) { + if (callerHasMoreInformationAboutArguments) { + if (OptCanonicalizer.getValue()) { + canonicalizer.applyIncremental(newGraph, context, parameterUsages); + } + } else { // TODO (chaeubl): if args are not more concrete, inlining should be avoided // in most cases or we could at least use the previous graph size + invoke // probability to check the inlining } - if (OptCanonicalizer.getValue()) { - canonicalizer.apply(newGraph, context); - } - return newGraph; } catch (Throwable e) { throw Debug.handle(e); @@ -117,12 +122,10 @@ * profiling info is mature, the resulting graph is cached. */ private static StructuredGraph parseBytecodes(StructuredGraph newGraph, HighTierContext context, CanonicalizerPhase canonicalizer) { - final boolean hasMatureProfilingInfo = newGraph.method().getProfilingInfo().isMature(); - if (context.getGraphBuilderSuite() != null) { context.getGraphBuilderSuite().apply(newGraph, context); } - assert newGraph.start().next() != null : "graph needs to be populated during PhasePosition.AFTER_PARSING"; + assert newGraph.start().next() != null : "graph needs to be populated the GraphBuilderSuite"; new DeadCodeEliminationPhase().apply(newGraph); @@ -130,7 +133,7 @@ canonicalizer.apply(newGraph, context); } - if (hasMatureProfilingInfo && context.getGraphCache() != null) { + if (context.getGraphCache() != null) { context.getGraphCache().put(newGraph.method(), newGraph.copy()); } return newGraph; diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Wed May 28 21:17:16 2014 +0200 @@ -47,9 +47,7 @@ import com.oracle.graal.phases.tiers.HighTierContext; import com.oracle.graal.phases.util.Providers; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import java.util.function.ToDoubleFunction; import static com.oracle.graal.compiler.common.GraalOptions.*; @@ -340,19 +338,21 @@ private void doInline(CallsiteHolder callerCallsiteHolder, MethodInvocation calleeInvocation, Assumptions callerAssumptions) { StructuredGraph callerGraph = callerCallsiteHolder.graph(); - Graph.Mark markBeforeInlining = callerGraph.getMark(); InlineInfo calleeInfo = calleeInvocation.callee(); try { try (Debug.Scope scope = Debug.scope("doInline", callerGraph)) { - List invokeUsages = calleeInfo.invoke().asNode().usages().snapshot(); - calleeInfo.inline(new Providers(context), callerAssumptions); + Set canonicalizedNodes = new HashSet<>(); + calleeInfo.invoke().asNode().usages().snapshotTo(canonicalizedNodes); + Collection parameterUsages = calleeInfo.inline(new Providers(context), callerAssumptions); + canonicalizedNodes.addAll(parameterUsages); callerAssumptions.record(calleeInvocation.assumptions()); metricInliningRuns.increment(); Debug.dump(callerGraph, "after %s", calleeInfo); if (OptCanonicalizer.getValue()) { Graph.Mark markBeforeCanonicalization = callerGraph.getMark(); - canonicalizer.applyIncremental(callerGraph, context, invokeUsages, markBeforeInlining); + + canonicalizer.applyIncremental(callerGraph, context, canonicalizedNodes); // process invokes that are possibly created during canonicalization for (Node newNode : callerGraph.getNewNodes(markBeforeCanonicalization)) { diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed May 28 21:17:16 2014 +0200 @@ -34,7 +34,6 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; -import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node; import com.oracle.graal.graph.spi.*; @@ -49,6 +48,7 @@ import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; import com.oracle.graal.phases.common.inlining.*; +import com.oracle.graal.phases.common.inlining.info.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.truffle.nodes.asserts.*; @@ -210,11 +210,10 @@ try (Indent indent = Debug.logAndIndent("inline graph %s", methodCallTargetNode.targetMethod())) { int nodeCountBefore = graph.getNodeCount(); - Mark mark = graph.getMark(); if (TraceTruffleExpansion.getValue()) { expansionLogger.preExpand(methodCallTargetNode, inlineGraph); } - List invokeUsages = methodCallTargetNode.invoke().asNode().usages().snapshot(); + List canonicalizedNodes = methodCallTargetNode.invoke().asNode().usages().snapshot(); Map inlined = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false); if (TraceTruffleExpansion.getValue()) { expansionLogger.postExpand(inlined); @@ -223,7 +222,8 @@ int nodeCountAfter = graph.getNodeCount(); Debug.dump(graph, "After inlining %s %+d (%d)", methodCallTargetNode.targetMethod().toString(), nodeCountAfter - nodeCountBefore, nodeCountAfter); } - canonicalizer.applyIncremental(graph, phaseContext, invokeUsages, mark); + AbstractInlineInfo.getInlinedParameterUsages(canonicalizedNodes, inlineGraph, inlined); + canonicalizer.applyIncremental(graph, phaseContext, canonicalizedNodes); changed = true; } diff -r 42eaa579e134 -r 5d0fbc245e55 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Wed May 28 17:41:59 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Wed May 28 21:17:16 2014 +0200 @@ -36,6 +36,7 @@ import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.debug.DebugMemUseTracker.Closeable; import com.oracle.graal.debug.internal.*; import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; @@ -102,6 +103,10 @@ public static final DebugTimer CompilationTime = Debug.timer("CompilationTime"); public static final DebugTimer CodeInstallationTime = Debug.timer("CodeInstallation"); + public static final DebugMemUseTracker PartialEvaluationMemUse = Debug.memUseTracker("TrufflePartialEvaluationMemUse"); + public static final DebugMemUseTracker CompilationMemUse = Debug.memUseTracker("TruffleCompilationMemUse"); + public static final DebugMemUseTracker CodeInstallationMemUse = Debug.memUseTracker("TruffleCodeInstallationMemUse"); + public void compileMethodImpl(final OptimizedCallTarget compilable) { final StructuredGraph graph; @@ -111,7 +116,7 @@ long timeCompilationStarted = System.nanoTime(); Assumptions assumptions = new Assumptions(true); - try (TimerCloseable a = PartialEvaluationTime.start()) { + try (TimerCloseable a = PartialEvaluationTime.start(); Closeable c = PartialEvaluationMemUse.start()) { graph = partialEvaluator.createGraph(compilable, assumptions); } @@ -156,7 +161,7 @@ } CompilationResult result = null; - try (TimerCloseable a = CompilationTime.start(); Scope s = Debug.scope("TruffleGraal.GraalCompiler", graph, providers.getCodeCache())) { + try (TimerCloseable a = CompilationTime.start(); Scope s = Debug.scope("TruffleGraal.GraalCompiler", graph, providers.getCodeCache()); Closeable c = CompilationMemUse.start()) { CodeCacheProvider codeCache = providers.getCodeCache(); CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false); CompilationResult compilationResult = new CompilationResult(name); @@ -183,7 +188,7 @@ result.setAssumptions(newAssumptions); InstalledCode installedCode; - try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache()); TimerCloseable a = CodeInstallationTime.start()) { + try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache()); TimerCloseable a = CodeInstallationTime.start(); Closeable c = CodeInstallationMemUse.start()) { installedCode = providers.getCodeCache().addMethod(graph.method(), result, speculationLog, predefinedInstalledCode); } catch (Throwable e) { throw Debug.handle(e);