# HG changeset patch # User Lukas Stadler # Date 1370616215 -7200 # Node ID eef9281ec13bac871c717572908f05c65be0fa6a # Parent 671bcaf13017459f8ade48c1ae4ea3b651dd2077 pull basic algorithm of PartialEscapeAnalysisPhase into new base class EffectsPhase diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Fri Jun 07 16:43:35 2013 +0200 @@ -309,7 +309,7 @@ Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(runtime(), assumptions, replacements); new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new PartialEscapeAnalysisPhase(false, false, new CanonicalizerPhase(true)).apply(graph, context); + new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context); new CullFrameStatesPhase().apply(graph); } @@ -333,7 +333,7 @@ } new DeadCodeEliminationPhase().apply(graph); canonicalizer.apply(graph, context); - new PartialEscapeAnalysisPhase(false, false, canonicalizer).apply(graph, context); + new PartialEscapePhase(false, canonicalizer).apply(graph, context); new CullFrameStatesPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Fri Jun 07 16:43:35 2013 +0200 @@ -222,7 +222,7 @@ HighTierContext context = new HighTierContext(runtime(), assumptions, replacements); new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); new DeadCodeEliminationPhase().apply(graph); - new PartialEscapeAnalysisPhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(true)).apply(graph, context); + new PartialEscapePhase(iterativeEscapeAnalysis, new CanonicalizerPhase(true)).apply(graph, context); Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count()); ReturnNode returnNode = graph.getNodes(ReturnNode.class).first(); if (expectedConstantResult != null) { diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Fri Jun 07 16:43:35 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.compiler.test.ea; -import static com.oracle.graal.phases.GraalOptions.*; import static org.junit.Assert.*; import java.util.concurrent.*; @@ -81,19 +80,6 @@ assertEquals(graph.getLocal(0), result); } - @SuppressWarnings("all") - public static int testSimpleReadSnippet(TestObject a, int b) throws Exception { - a.callable = new TestInt(b, 9); - return a.callable.call(); - } - - @Test - public void testSimpleRead() { - ValueNode result = getReturn("testSimpleReadSnippet").result(); - assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty()); - assertEquals(graph.getLocal(1), result); - } - final ReturnNode getReturn(String snippet) { processMethod(snippet); assertEquals(1, graph.getNodes(ReturnNode.class).count()); @@ -102,8 +88,7 @@ private void processMethod(final String snippet) { graph = parse(snippet); - OptEarlyReadElimination.setValue(true); HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements); - new IterativeInliningPhase(replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, false, new CanonicalizerPhase(true)).apply(graph, context); + new IterativeInliningPhase(replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, new CanonicalizerPhase(true)).apply(graph, context); } } diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Fri Jun 07 14:27:04 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.compiler.test.ea; - -import static org.junit.Assert.*; - -import java.util.concurrent.*; - -import org.junit.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.common.*; -import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.virtual.phases.ea.*; - -public class PEAReadEliminationTest extends GraalCompilerTest { - - private StructuredGraph graph; - - public static Object staticField; - - public static class TestObject implements Callable { - - public int x; - public int y; - - public TestObject(int x, int y) { - this.x = x; - this.y = y; - } - - @Override - public Integer call() throws Exception { - return x; - } - } - - public static class TestObject2 { - - public Object x; - public Object y; - - public TestObject2(Object x, Object y) { - this.x = x; - this.y = y; - } - } - - @SuppressWarnings("all") - public static int testSimpleSnippet(TestObject a) { - a.x = 2; - staticField = a; - return a.x; - } - - @Test - public void testSimple() { - ValueNode result = getReturn("testSimpleSnippet").result(); - assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty()); - assertTrue(result.isConstant()); - assertEquals(2, result.asConstant().asInt()); - } - - @SuppressWarnings("all") - public static int testSimpleConflictSnippet(TestObject a, TestObject b) { - a.x = 2; - b.x = 3; - staticField = a; - return a.x; - } - - @Test - public void testSimpleConflict() { - ValueNode result = getReturn("testSimpleConflictSnippet").result(); - assertFalse(result.isConstant()); - assertTrue(result instanceof LoadFieldNode); - } - - @SuppressWarnings("all") - public static int testParamSnippet(TestObject a, int b) { - a.x = b; - return a.x; - } - - @Test - public void testParam() { - ValueNode result = getReturn("testParamSnippet").result(); - assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty()); - assertEquals(graph.getLocal(1), result); - } - - @SuppressWarnings("all") - public static int testMaterializedSnippet(int a) { - TestObject obj = new TestObject(a, 0); - staticField = obj; - return obj.x; - } - - @Test - public void testMaterialized() { - ValueNode result = getReturn("testMaterializedSnippet").result(); - assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty()); - assertEquals(graph.getLocal(0), result); - } - - @SuppressWarnings("all") - public static int testSimpleLoopSnippet(TestObject obj, int a, int b) { - obj.x = a; - for (int i = 0; i < 10; i++) { - staticField = obj; - } - return obj.x; - } - - @Test - public void testSimpleLoop() { - ValueNode result = getReturn("testSimpleLoopSnippet").result(); - assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty()); - assertEquals(graph.getLocal(1), result); - } - - @SuppressWarnings("all") - public static int testBadLoopSnippet(TestObject obj, TestObject obj2, int a, int b) { - obj.x = a; - for (int i = 0; i < 10; i++) { - staticField = obj; - obj2.x = 10; - obj.x = 0; - } - return obj.x; - } - - @Test - public void testBadLoop() { - ValueNode result = getReturn("testBadLoopSnippet").result(); - assertEquals(0, graph.getNodes(LoadFieldNode.class).count()); - assertTrue(result instanceof ProxyNode); - assertTrue(((ProxyNode) result).value() instanceof PhiNode); - } - - @SuppressWarnings("all") - public static int testBadLoop2Snippet(TestObject obj, TestObject obj2, int a, int b) { - obj.x = a; - for (int i = 0; i < 10; i++) { - obj.x = 0; - obj2.x = 10; - } - return obj.x; - } - - @Test - public void testBadLoop2() { - ValueNode result = getReturn("testBadLoop2Snippet").result(); - assertEquals(1, graph.getNodes(LoadFieldNode.class).count()); - assertTrue(result instanceof LoadFieldNode); - } - - @SuppressWarnings("all") - public static int testPhiSnippet(TestObject a, int b) { - if (b < 0) { - a.x = 1; - } else { - a.x = 2; - } - return a.x; - } - - @Test - public void testPhi() { - ValueNode result = getReturn("testPhiSnippet").result(); - assertTrue(graph.getNodes(LoadFieldNode.class).isEmpty()); - assertTrue(result instanceof PhiNode); - PhiNode phi = (PhiNode) result; - assertTrue(phi.valueAt(0).isConstant()); - assertTrue(phi.valueAt(1).isConstant()); - assertEquals(1, phi.valueAt(0).asConstant().asInt()); - assertEquals(2, phi.valueAt(1).asConstant().asInt()); - } - - @SuppressWarnings("all") - public static void testSimpleStoreSnippet(TestObject a, int b) { - a.x = b; - a.x = b; - } - - @Test - public void testSimpleStore() { - processMethod("testSimpleStoreSnippet"); - assertEquals(1, graph.getNodes().filter(StoreFieldNode.class).count()); - } - - final ReturnNode getReturn(String snippet) { - processMethod(snippet); - assertEquals(1, graph.getNodes(ReturnNode.class).count()); - return graph.getNodes(ReturnNode.class).first(); - } - - private void processMethod(final String snippet) { - graph = parse(snippet); - Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(runtime(), assumptions, replacements); - new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new PartialEscapeAnalysisPhase(false, true, new CanonicalizerPhase(true)).apply(graph, context); - } -} diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Fri Jun 07 16:43:35 2013 +0200 @@ -166,7 +166,7 @@ new DeadCodeEliminationPhase().apply(graph); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); canonicalizer.apply(graph, context); - new PartialEscapeAnalysisPhase(false, false, canonicalizer).apply(graph, context); + new PartialEscapePhase(false, canonicalizer).apply(graph, context); new CullFrameStatesPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); diff -r 671bcaf13017 -r eef9281ec13b 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 Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Fri Jun 07 16:43:35 2013 +0200 @@ -149,7 +149,7 @@ if (Inline.getValue() && !plan.isPhaseDisabled(InliningPhase.class)) { if (IterativeInlining.getValue()) { - new IterativeInliningPhase(replacements, cache, plan, optimisticOpts, OptEarlyReadElimination.getValue(), canonicalizer).apply(graph, highTierContext); + new IterativeInliningPhase(replacements, cache, plan, optimisticOpts, canonicalizer).apply(graph, highTierContext); } else { new InliningPhase(runtime, null, replacements, assumptions, cache, plan, optimisticOpts).apply(graph); new DeadCodeEliminationPhase().apply(graph); diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Fri Jun 07 16:43:35 2013 +0200 @@ -45,7 +45,7 @@ } if (PartialEscapeAnalysis.getValue()) { - addPhase(new PartialEscapeAnalysisPhase(true, OptEarlyReadElimination.getValue(), canonicalizer)); + addPhase(new PartialEscapePhase(true, canonicalizer)); } if (OptConvertDeoptsToGuards.getValue()) { diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Fri Jun 07 16:43:35 2013 +0200 @@ -79,13 +79,6 @@ if (fieldIndex != -1) { tool.replaceWith(state.getEntry(fieldIndex)); } - } else { - ValueNode cachedValue = tool.getReadCache(object(), field()); - if (cachedValue != null) { - tool.replaceWithValue(cachedValue); - } else { - tool.addReadCache(object(), field(), this); - } } } } diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Fri Jun 07 16:43:35 2013 +0200 @@ -77,12 +77,6 @@ tool.setVirtualEntry(state, fieldIndex, value()); tool.delete(); } - } else { - if (value() == tool.getReadCache(object(), field())) { - tool.delete(); - } - tool.killReadCache(field()); - tool.addReadCache(object(), field(), value()); } } } diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Fri Jun 07 16:43:35 2013 +0200 @@ -153,10 +153,4 @@ */ void replaceWith(ValueNode value); - void addReadCache(ValueNode object, ResolvedJavaField identity, ValueNode value); - - ValueNode getReadCache(ValueNode object, ResolvedJavaField identity); - - void killReadCache(ResolvedJavaField identity); - } diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Fri Jun 07 16:43:35 2013 +0200 @@ -261,8 +261,6 @@ @Option(help = "") public static final OptionValue OptReadElimination = new OptionValue<>(true); @Option(help = "") - public static final OptionValue OptEarlyReadElimination = new OptionValue<>(true); - @Option(help = "") public static final OptionValue OptCanonicalizer = new OptionValue<>(true); @Option(help = "") public static final OptionValue OptCanonicalizeReads = new OptionValue<>(true); diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java Fri Jun 07 16:43:35 2013 +0200 @@ -63,7 +63,7 @@ } /** - * Tests monitor operations on {@link PartialEscapeAnalysisPhase virtual objects}. + * Tests monitor operations on {@link PartialEscapePhase virtual objects}. */ @Test public void test3() { diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java Fri Jun 07 14:27:04 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,306 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.virtual.phases.ea; - -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; -import com.oracle.graal.nodes.virtual.*; - -public class BlockState { - - protected final IdentityHashMap objectStates = new IdentityHashMap<>(); - protected final IdentityHashMap objectAliases; - protected final IdentityHashMap scalarAliases; - final HashMap readCache; - - static class ReadCacheEntry { - - public final ResolvedJavaField identity; - public final ValueNode object; - - public ReadCacheEntry(ResolvedJavaField identity, ValueNode object) { - this.identity = identity; - this.object = object; - } - - @Override - public int hashCode() { - int result = 31 + ((identity == null) ? 0 : identity.hashCode()); - return 31 * result + ((object == null) ? 0 : object.hashCode()); - } - - @Override - public boolean equals(Object obj) { - ReadCacheEntry other = (ReadCacheEntry) obj; - return identity == other.identity && object == other.object; - } - - @Override - public String toString() { - return object + ":" + identity; - } - } - - public BlockState() { - objectAliases = new IdentityHashMap<>(); - scalarAliases = new IdentityHashMap<>(); - readCache = new HashMap<>(); - } - - public BlockState(BlockState other) { - for (Map.Entry entry : other.objectStates.entrySet()) { - objectStates.put(entry.getKey(), entry.getValue().cloneState()); - } - objectAliases = new IdentityHashMap<>(other.objectAliases); - scalarAliases = new IdentityHashMap<>(other.scalarAliases); - readCache = new HashMap<>(other.readCache); - } - - public void addReadCache(ValueNode object, ResolvedJavaField identity, ValueNode value) { - ValueNode cacheObject; - ObjectState obj = getObjectState(object); - if (obj != null) { - assert !obj.isVirtual(); - cacheObject = obj.getMaterializedValue(); - } else { - cacheObject = object; - } - readCache.put(new ReadCacheEntry(identity, cacheObject), value); - } - - public ValueNode getReadCache(ValueNode object, ResolvedJavaField identity) { - ValueNode cacheObject; - ObjectState obj = getObjectState(object); - if (obj != null) { - assert !obj.isVirtual(); - cacheObject = obj.getMaterializedValue(); - } else { - cacheObject = object; - } - ValueNode cacheValue = readCache.get(new ReadCacheEntry(identity, cacheObject)); - obj = getObjectState(cacheValue); - if (obj != null) { - assert !obj.isVirtual(); - cacheValue = obj.getMaterializedValue(); - } else { - cacheValue = getScalarAlias(cacheValue); - } - return cacheValue; - } - - public void killReadCache() { - readCache.clear(); - } - - public void killReadCache(ResolvedJavaField identity) { - Iterator> iter = readCache.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = iter.next(); - if (entry.getKey().identity == identity) { - iter.remove(); - } - } - } - - public ObjectState getObjectState(VirtualObjectNode object) { - assert objectStates.containsKey(object); - return objectStates.get(object); - } - - public ObjectState getObjectStateOptional(VirtualObjectNode object) { - return objectStates.get(object); - } - - public ObjectState getObjectState(ValueNode value) { - VirtualObjectNode object = objectAliases.get(value); - return object == null ? null : getObjectState(object); - } - - public BlockState cloneState() { - return new BlockState(this); - } - - public BlockState cloneEmptyState() { - return new BlockState(); - } - - public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, EscapeState state, GraphEffectList materializeEffects) { - PartialEscapeClosure.METRIC_MATERIALIZATIONS.increment(); - List objects = new ArrayList<>(2); - List values = new ArrayList<>(8); - List locks = new ArrayList<>(2); - List otherAllocations = new ArrayList<>(2); - materializeWithCommit(fixed, virtual, objects, locks, values, otherAllocations, state); - - materializeEffects.addMaterializationBefore(fixed, objects, locks, values, otherAllocations); - } - - private void materializeWithCommit(FixedNode fixed, VirtualObjectNode virtual, List objects, List locks, List values, List otherAllocations, - EscapeState state) { - VirtualUtil.trace("materializing %s", virtual); - ObjectState obj = getObjectState(virtual); - - ValueNode[] entries = obj.getEntries(); - ValueNode representation = virtual.getMaterializedRepresentation(fixed, entries, obj.getLocks()); - obj.escape(representation, state); - if (representation instanceof AllocatedObjectNode) { - objects.add((AllocatedObjectNode) representation); - locks.add(obj.getLocks()); - int pos = values.size(); - while (values.size() < pos + entries.length) { - values.add(null); - } - for (int i = 0; i < entries.length; i++) { - ObjectState entryObj = getObjectState(entries[i]); - if (entryObj != null) { - if (entryObj.isVirtual()) { - materializeWithCommit(fixed, entryObj.getVirtualObject(), objects, locks, values, otherAllocations, state); - } - values.set(pos + i, entryObj.getMaterializedValue()); - } else { - values.set(pos + i, entries[i]); - } - } - if (virtual instanceof VirtualInstanceNode) { - VirtualInstanceNode instance = (VirtualInstanceNode) virtual; - for (int i = 0; i < entries.length; i++) { - readCache.put(new ReadCacheEntry(instance.field(i), representation), values.get(pos + i)); - } - } - } else { - otherAllocations.add(representation); - assert obj.getLocks().length == 0; - } - } - - void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node, NodeBitMap usages) { - objectAliases.put(node, virtual); - if (node.isAlive()) { - for (Node usage : node.usages()) { - markVirtualUsages(usage, usages); - } - } - } - - private void markVirtualUsages(Node node, NodeBitMap usages) { - if (!usages.isNew(node)) { - usages.mark(node); - } - if (node instanceof VirtualState) { - for (Node usage : node.usages()) { - markVirtualUsages(usage, usages); - } - } - } - - public void addObject(VirtualObjectNode virtual, ObjectState state) { - objectStates.put(virtual, state); - } - - public void addScalarAlias(ValueNode alias, ValueNode value) { - scalarAliases.put(alias, value); - } - - public ValueNode getScalarAlias(ValueNode alias) { - ValueNode result = scalarAliases.get(alias); - return result == null ? alias : result; - } - - public Iterable getStates() { - return objectStates.values(); - } - - public Collection getVirtualObjects() { - return objectAliases.values(); - } - - @Override - public String toString() { - return objectStates + " " + readCache; - } - - public void meetAliases(List states) { - objectAliases.putAll(states.get(0).objectAliases); - scalarAliases.putAll(states.get(0).scalarAliases); - for (int i = 1; i < states.size(); i++) { - BlockState state = states.get(i); - meetMaps(objectAliases, state.objectAliases); - meetMaps(scalarAliases, state.scalarAliases); - } - } - - public Map getReadCache() { - return readCache; - } - - public boolean equivalentTo(BlockState other) { - if (this == other) { - return true; - } - boolean objectAliasesEqual = compareMaps(objectAliases, other.objectAliases); - boolean objectStatesEqual = compareMaps(objectStates, other.objectStates); - boolean readCacheEqual = compareMapsNoSize(readCache, other.readCache); - boolean scalarAliasesEqual = scalarAliases.equals(other.scalarAliases); - return objectAliasesEqual && objectStatesEqual && readCacheEqual && scalarAliasesEqual; - } - - protected static boolean compareMaps(Map left, Map right) { - if (left.size() != right.size()) { - return false; - } - return compareMapsNoSize(left, right); - } - - protected static boolean compareMapsNoSize(Map left, Map right) { - if (left == right) { - return true; - } - for (Map.Entry entry : right.entrySet()) { - K key = entry.getKey(); - V value = entry.getValue(); - assert value != null; - V otherValue = left.get(key); - if (otherValue != value && !value.equals(otherValue)) { - return false; - } - } - return true; - } - - protected static void meetMaps(Map target, Map source) { - Iterator> iter = target.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = iter.next(); - if (source.containsKey(entry.getKey())) { - assert source.get(entry.getKey()) == entry.getValue(); - } else { - iter.remove(); - } - } - } - -} diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsBlockState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsBlockState.java Fri Jun 07 16:43:35 2013 +0200 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.virtual.phases.ea; + +import java.util.*; + +import com.oracle.graal.nodes.*; + +public abstract class EffectsBlockState> { + + protected final IdentityHashMap scalarAliases; + + protected EffectsBlockState() { + scalarAliases = new IdentityHashMap<>(); + } + + protected EffectsBlockState(EffectsBlockState other) { + scalarAliases = new IdentityHashMap<>(other.scalarAliases); + } + + public void addScalarAlias(ValueNode alias, ValueNode value) { + scalarAliases.put(alias, value); + } + + public ValueNode getScalarAlias(ValueNode alias) { + ValueNode result = scalarAliases.get(alias); + return result == null ? alias : result; + } + + @Override + public String toString() { + return "Scalar Aliases: " + scalarAliases.toString(); + } + + public void meetAliases(List states) { + scalarAliases.putAll(states.get(0).scalarAliases); + for (int i = 1; i < states.size(); i++) { + EffectsBlockState state = states.get(i); + meetMaps(scalarAliases, state.scalarAliases); + } + } + + public boolean equivalentTo(T other) { + if (this == other) { + return true; + } + return scalarAliases.equals(other.scalarAliases); + } + + protected static boolean compareMaps(Map left, Map right) { + if (left.size() != right.size()) { + return false; + } + return compareMapsNoSize(left, right); + } + + protected static boolean compareMapsNoSize(Map left, Map right) { + if (left == right) { + return true; + } + for (Map.Entry entry : right.entrySet()) { + K key = entry.getKey(); + V value = entry.getValue(); + assert value != null; + V otherValue = left.get(key); + if (otherValue != value && !value.equals(otherValue)) { + return false; + } + } + return true; + } + + protected static void meetMaps(Map target, Map source) { + Iterator> iter = target.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = iter.next(); + if (source.containsKey(entry.getKey())) { + assert source.get(entry.getKey()) == entry.getValue(); + } else { + iter.remove(); + } + } + } + +} diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Fri Jun 07 16:43:35 2013 +0200 @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.virtual.phases.ea; + +import java.util.*; + +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.phases.graph.*; +import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; +import com.oracle.graal.phases.graph.ReentrantBlockIterator.LoopInfo; +import com.oracle.graal.phases.schedule.*; +import com.oracle.graal.virtual.phases.ea.EffectList.Effect; + +public abstract class EffectsClosure> extends EffectsPhase.Closure { + + private final SchedulePhase schedule; + + protected final BlockMap blockEffects; + private final IdentityHashMap loopMergeEffects = new IdentityHashMap<>(); + + private boolean changed; + + public EffectsClosure(SchedulePhase schedule) { + this.schedule = schedule; + this.blockEffects = new BlockMap<>(schedule.getCFG()); + for (Block block : schedule.getCFG().getBlocks()) { + blockEffects.put(block, new GraphEffectList()); + } + } + + @Override + public boolean hasChanged() { + return changed; + } + + @Override + public void applyEffects() { + final StructuredGraph graph = schedule.getCFG().graph; + final ArrayList obsoleteNodes = new ArrayList<>(0); + BlockIteratorClosure closure = new BlockIteratorClosure() { + + @Override + protected Void getInitialState() { + return null; + } + + private void apply(GraphEffectList effects, Object context) { + if (!effects.isEmpty()) { + Debug.log(" ==== effects for %s", context); + for (Effect effect : effects) { + effect.apply(graph, obsoleteNodes); + if (effect.isVisible()) { + Debug.log(" %s", effect); + } + } + } + } + + @Override + protected Void processBlock(Block block, Void currentState) { + apply(blockEffects.get(block), block); + Debug.dump(graph, "after processing block %s", block); + return currentState; + } + + @Override + protected Void merge(Block merge, List states) { + return null; + } + + @Override + protected Void cloneState(Void oldState) { + return oldState; + } + + @Override + protected List processLoop(Loop loop, Void initialState) { + LoopInfo info = ReentrantBlockIterator.processLoop(this, loop, initialState); + apply(loopMergeEffects.get(loop), loop); + return info.exitStates; + } + }; + ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock()); + assert VirtualUtil.assertNonReachable(graph, obsoleteNodes); + } + + @Override + protected BlockT processBlock(Block block, BlockT state) { + VirtualUtil.trace("\nBlock: %s (", block); + + GraphEffectList effects = blockEffects.get(block); + FixedWithNextNode lastFixedNode = null; + for (Node node : schedule.getBlockToNodesMap().get(block)) { + changed |= processNode(node, state, effects, lastFixedNode); + if (node instanceof FixedWithNextNode) { + lastFixedNode = (FixedWithNextNode) node; + } + } + VirtualUtil.trace(")\n end state: %s\n", state); + return state; + } + + protected abstract boolean processNode(Node node, BlockT state, GraphEffectList effects, FixedWithNextNode lastFixedNode); + + @Override + protected BlockT merge(Block merge, List states) { + assert blockEffects.get(merge).isEmpty(); + MergeProcessor processor = createMergeProcessor(merge); + processor.merge(states); + blockEffects.get(merge).addAll(processor.mergeEffects); + blockEffects.get(merge).addAll(processor.afterMergeEffects); + return processor.newState; + } + + @Override + protected final List processLoop(Loop loop, BlockT initialState) { + BlockT loopEntryState = initialState; + BlockT lastMergedState = initialState; + MergeProcessor mergeProcessor = createMergeProcessor(loop.header); + for (int iteration = 0; iteration < 10; iteration++) { + LoopInfo info = ReentrantBlockIterator.processLoop(this, loop, cloneState(lastMergedState)); + + List states = new ArrayList<>(); + states.add(initialState); + states.addAll(info.endStates); + mergeProcessor.merge(states); + + Debug.log("================== %s", loop.header); + Debug.log("%s", mergeProcessor.newState); + Debug.log("===== vs."); + Debug.log("%s", lastMergedState); + + if (mergeProcessor.newState.equivalentTo(lastMergedState)) { + blockEffects.get(loop.header).insertAll(mergeProcessor.mergeEffects, 0); + loopMergeEffects.put(loop, mergeProcessor.afterMergeEffects); + + assert info.exitStates.size() == loop.exits.size(); + for (int i = 0; i < loop.exits.size(); i++) { + BlockT exitState = info.exitStates.get(i); + assert exitState != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header; + processLoopExit((LoopExitNode) loop.exits.get(i).getBeginNode(), loopEntryState, exitState, blockEffects.get(loop.exits.get(i))); + } + + return info.exitStates; + } else { + lastMergedState = mergeProcessor.newState; + for (Block block : loop.blocks) { + blockEffects.get(block).clear(); + } + } + } + throw new GraalInternalError("too many iterations at %s", loop); + } + + protected abstract void processLoopExit(LoopExitNode exitNode, BlockT initialState, BlockT exitState, GraphEffectList effects); + + protected abstract MergeProcessor createMergeProcessor(Block merge); + + protected class MergeProcessor { + + protected final Block mergeBlock; + protected final MergeNode merge; + + protected final GraphEffectList mergeEffects; + protected final GraphEffectList afterMergeEffects; + protected final BlockT newState; + + public MergeProcessor(Block mergeBlock) { + this.mergeBlock = mergeBlock; + this.newState = getInitialState(); + this.merge = (MergeNode) mergeBlock.getBeginNode(); + this.mergeEffects = new GraphEffectList(); + this.afterMergeEffects = new GraphEffectList(); + } + + protected void merge(List states) { + newState.meetAliases(states); + } + } +} diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Fri Jun 07 16:43:35 2013 +0200 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.virtual.phases.ea; + +import static com.oracle.graal.phases.GraalOptions.*; + +import java.util.concurrent.*; + +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.graph.*; +import com.oracle.graal.phases.schedule.*; +import com.oracle.graal.phases.tiers.*; + +public abstract class EffectsPhase extends BasePhase { + + public abstract static class Closure extends ReentrantBlockIterator.BlockIteratorClosure { + + public abstract boolean hasChanged(); + + public abstract void applyEffects(); + } + + private final int maxIterations; + private CanonicalizerPhase canonicalizer; + + public EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer) { + this.maxIterations = maxIterations; + this.canonicalizer = canonicalizer; + } + + @Override + protected void run(StructuredGraph graph, PhaseContextT context) { + runAnalysis(graph, context); + } + + public boolean runAnalysis(final StructuredGraph graph, final PhaseContextT context) { + boolean changed = false; + for (int iteration = 0; iteration < maxIterations; iteration++) { + boolean currentChanged = Debug.scope("iteration " + iteration, new Callable() { + + @Override + public Boolean call() { + SchedulePhase schedule = new SchedulePhase(); + schedule.apply(graph, false); + Closure closure = createEffectsClosure(context, schedule); + ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock()); + + if (!closure.hasChanged()) { + return false; + } + + // apply the effects collected during this iteration + closure.applyEffects(); + + Debug.dump(graph, "after " + getName() + " iteration"); + + new DeadCodeEliminationPhase().apply(graph); + + if (OptCanonicalizer.getValue()) { + canonicalizer.apply(graph, context); + } + + return true; + } + }); + if (!currentChanged) { + break; + } + changed |= currentChanged; + } + return changed; + } + + protected abstract Closure createEffectsClosure(PhaseContextT context, SchedulePhase schedule); +} diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java Fri Jun 07 16:43:35 2013 +0200 @@ -41,15 +41,13 @@ private final Replacements replacements; private final GraphCache cache; private final OptimisticOptimizations optimisticOpts; - private final boolean readElimination; private final CanonicalizerPhase canonicalizer; - public IterativeInliningPhase(Replacements replacements, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, boolean readElimination, CanonicalizerPhase canonicalizer) { + public IterativeInliningPhase(Replacements replacements, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, CanonicalizerPhase canonicalizer) { this.replacements = replacements; this.cache = cache; this.plan = plan; this.optimisticOpts = optimisticOpts; - this.readElimination = readElimination; this.canonicalizer = canonicalizer; } @@ -73,11 +71,11 @@ @Override public Boolean call() { boolean progress = false; - PartialEscapeAnalysisPhase ea = new PartialEscapeAnalysisPhase(false, readElimination, canonicalizer); + PartialEscapePhase ea = new PartialEscapePhase(false, canonicalizer); boolean eaResult = ea.runAnalysis(graph, context); progress |= eaResult; - Map hints = PEAInliningHints.getValue() ? PartialEscapeAnalysisPhase.getHints(graph) : null; + Map hints = PEAInliningHints.getValue() ? PartialEscapePhase.getHints(graph) : null; InliningPhase inlining = new InliningPhase(context.getRuntime(), hints, replacements, context.getAssumptions(), cache, plan, optimisticOpts); inlining.setMaxMethodsPerInlining(simple ? 1 : Integer.MAX_VALUE); diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java Fri Jun 07 16:43:35 2013 +0200 @@ -34,7 +34,7 @@ * the fields or array elements (called "entries") and the lock count if the object is still * virtual. If the object was materialized, it contains the current materialized value. */ -class ObjectState extends Virtualizable.State { +public class ObjectState extends Virtualizable.State { private static final int[] EMPTY_INT_ARRAY = new int[0]; diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Fri Jun 07 14:27:04 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.virtual.phases.ea; - -import static com.oracle.graal.phases.GraalOptions.*; - -import java.util.*; -import java.util.concurrent.*; - -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.util.*; -import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.common.*; -import com.oracle.graal.phases.graph.*; -import com.oracle.graal.phases.schedule.*; -import com.oracle.graal.phases.tiers.*; - -public class PartialEscapeAnalysisPhase extends BasePhase { - - public abstract static class Closure extends ReentrantBlockIterator.BlockIteratorClosure { - - public abstract boolean hasChanged(); - - public abstract void applyEffects(); - } - - private final boolean iterative; - private final boolean readElimination; - private final CanonicalizerPhase canonicalizer; - - public PartialEscapeAnalysisPhase(boolean iterative, boolean readElimination, CanonicalizerPhase canonicalizer) { - this.iterative = iterative; - this.readElimination = readElimination; - this.canonicalizer = canonicalizer; - } - - @Override - protected void run(StructuredGraph graph, PhaseContext context) { - runAnalysis(graph, context); - } - - public boolean runAnalysis(final StructuredGraph graph, final PhaseContext context) { - if (!VirtualUtil.matches(graph, EscapeAnalyzeOnly.getValue())) { - return false; - } - - if (!readElimination) { - boolean analyzableNodes = false; - for (Node node : graph.getNodes()) { - if (node instanceof VirtualizableAllocation) { - analyzableNodes = true; - break; - } - } - if (!analyzableNodes) { - return false; - } - } - - boolean continueIteration = true; - boolean changed = false; - for (int iteration = 0; iteration < EscapeAnalysisIterations.getValue() && continueIteration; iteration++) { - boolean currentChanged = Debug.scope("iteration " + iteration, new Callable() { - - @Override - public Boolean call() { - - SchedulePhase schedule = new SchedulePhase(); - schedule.apply(graph, false); - Closure closure = createAnalysisClosure(context, schedule); - ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock()); - - if (!closure.hasChanged()) { - return false; - } - - // apply the effects collected during the escape analysis iteration - closure.applyEffects(); - - Debug.dump(graph, "after PartialEscapeAnalysis iteration"); - - new DeadCodeEliminationPhase().apply(graph); - - if (OptCanonicalizer.getValue()) { - canonicalizer.apply(graph, context); - } - - return true; - } - }); - continueIteration = currentChanged && iterative; - changed |= currentChanged; - } - - return changed; - } - - protected Closure createAnalysisClosure(PhaseContext context, SchedulePhase schedule) { - return new PartialEscapeClosure<>(schedule, context.getRuntime(), context.getAssumptions()); - } - - public static Map getHints(StructuredGraph graph) { - NodesToDoubles probabilities = new ComputeProbabilityClosure(graph).apply(); - Map hints = null; - for (CommitAllocationNode commit : graph.getNodes(CommitAllocationNode.class)) { - double sum = 0; - double invokeSum = 0; - for (Node commitUsage : commit.usages()) { - for (Node usage : commitUsage.usages()) { - if (usage instanceof FixedNode) { - sum += probabilities.get((FixedNode) usage); - } else { - if (usage instanceof MethodCallTargetNode) { - invokeSum += probabilities.get(((MethodCallTargetNode) usage).invoke().asNode()); - } - for (Node secondLevelUage : usage.usages()) { - if (secondLevelUage instanceof FixedNode) { - sum += probabilities.get(((FixedNode) secondLevelUage)); - } - } - } - } - } - // TODO(lstadler) get rid of this magic number - if (sum > 100 && invokeSum > 0) { - for (Node commitUsage : commit.usages()) { - for (Node usage : commitUsage.usages()) { - if (usage instanceof MethodCallTargetNode) { - if (hints == null) { - hints = new HashMap<>(); - } - Invoke invoke = ((MethodCallTargetNode) usage).invoke(); - hints.put(invoke, sum / invokeSum); - } - } - } - } - } - return hints; - } -} diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java Fri Jun 07 16:43:35 2013 +0200 @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.virtual.phases.ea; + +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; +import com.oracle.graal.nodes.virtual.*; + +public abstract class PartialEscapeBlockState> extends EffectsBlockState { + + protected final IdentityHashMap objectStates = new IdentityHashMap<>(); + protected final IdentityHashMap objectAliases; + + /** + * Final subclass of PartialEscapeBlockState, for performance and to make everything behave + * nicely with generics. + */ + public static final class Final extends PartialEscapeBlockState { + + public Final() { + } + + public Final(Final other) { + super(other); + } + } + + protected PartialEscapeBlockState() { + objectAliases = new IdentityHashMap<>(); + } + + protected PartialEscapeBlockState(PartialEscapeBlockState other) { + super(other); + for (Map.Entry entry : other.objectStates.entrySet()) { + objectStates.put(entry.getKey(), entry.getValue().cloneState()); + } + objectAliases = new IdentityHashMap<>(other.objectAliases); + } + + public ObjectState getObjectState(VirtualObjectNode object) { + assert objectStates.containsKey(object); + return objectStates.get(object); + } + + public ObjectState getObjectStateOptional(VirtualObjectNode object) { + return objectStates.get(object); + } + + public ObjectState getObjectState(ValueNode value) { + VirtualObjectNode object = objectAliases.get(value); + return object == null ? null : getObjectState(object); + } + + public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, EscapeState state, GraphEffectList materializeEffects) { + PartialEscapeClosure.METRIC_MATERIALIZATIONS.increment(); + List objects = new ArrayList<>(2); + List values = new ArrayList<>(8); + List locks = new ArrayList<>(2); + List otherAllocations = new ArrayList<>(2); + materializeWithCommit(fixed, virtual, objects, locks, values, otherAllocations, state); + + materializeEffects.addMaterializationBefore(fixed, objects, locks, values, otherAllocations); + } + + private void materializeWithCommit(FixedNode fixed, VirtualObjectNode virtual, List objects, List locks, List values, List otherAllocations, + EscapeState state) { + ObjectState obj = getObjectState(virtual); + + ValueNode[] entries = obj.getEntries(); + ValueNode representation = virtual.getMaterializedRepresentation(fixed, entries, obj.getLocks()); + obj.escape(representation, state); + if (representation instanceof AllocatedObjectNode) { + objects.add((AllocatedObjectNode) representation); + locks.add(obj.getLocks()); + int pos = values.size(); + while (values.size() < pos + entries.length) { + values.add(null); + } + for (int i = 0; i < entries.length; i++) { + ObjectState entryObj = getObjectState(entries[i]); + if (entryObj != null) { + if (entryObj.isVirtual()) { + materializeWithCommit(fixed, entryObj.getVirtualObject(), objects, locks, values, otherAllocations, state); + } + values.set(pos + i, entryObj.getMaterializedValue()); + } else { + values.set(pos + i, entries[i]); + } + } + objectMaterialized(virtual, (AllocatedObjectNode) representation, values.subList(pos, pos + entries.length)); + } else { + VirtualUtil.trace("materialized %s as %s", virtual, representation); + otherAllocations.add(representation); + assert obj.getLocks().length == 0; + } + } + + protected void objectMaterialized(VirtualObjectNode virtual, AllocatedObjectNode representation, List values) { + VirtualUtil.trace("materialized %s as %s with values %s", virtual, representation, values); + } + + void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node, NodeBitMap usages) { + objectAliases.put(node, virtual); + if (node.isAlive()) { + for (Node usage : node.usages()) { + markVirtualUsages(usage, usages); + } + } + } + + private void markVirtualUsages(Node node, NodeBitMap usages) { + if (!usages.isNew(node)) { + usages.mark(node); + } + if (node instanceof VirtualState) { + for (Node usage : node.usages()) { + markVirtualUsages(usage, usages); + } + } + } + + public void addObject(VirtualObjectNode virtual, ObjectState state) { + objectStates.put(virtual, state); + } + + public Iterable getStates() { + return objectStates.values(); + } + + public Collection getVirtualObjects() { + return objectAliases.values(); + } + + @Override + public String toString() { + return super.toString() + ", Object Aliases: " + objectAliases + ", Object States: " + objectStates; + } + + @Override + public void meetAliases(List states) { + super.meetAliases(states); + objectAliases.putAll(states.get(0).objectAliases); + for (int i = 1; i < states.size(); i++) { + meetMaps(objectAliases, states.get(i).objectAliases); + } + } + + @Override + public boolean equivalentTo(T other) { + if (!compareMaps(objectAliases, other.objectAliases) || !compareMaps(objectStates, other.objectStates)) { + return false; + } + return super.equivalentTo(other); + } + + protected static boolean compareMaps(Map left, Map right) { + if (left.size() != right.size()) { + return false; + } + return compareMapsNoSize(left, right); + } + + protected static boolean compareMapsNoSize(Map left, Map right) { + if (left == right) { + return true; + } + for (Map.Entry entry : right.entrySet()) { + K key = entry.getKey(); + V value = entry.getValue(); + assert value != null; + V otherValue = left.get(key); + if (otherValue != value && !value.equals(otherValue)) { + return false; + } + } + return true; + } + + protected static void meetMaps(Map target, Map source) { + Iterator> iter = target.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = iter.next(); + if (source.containsKey(entry.getKey())) { + assert source.get(entry.getKey()) == entry.getValue(); + } else { + iter.remove(); + } + } + } + +} diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Fri Jun 07 16:43:35 2013 +0200 @@ -22,9 +22,6 @@ */ package com.oracle.graal.virtual.phases.ea; -import static com.oracle.graal.api.meta.LocationIdentity.*; -import static com.oracle.graal.phases.GraalOptions.*; - import java.util.*; import com.oracle.graal.api.code.*; @@ -35,20 +32,14 @@ import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.VirtualState.NodeClosure; import com.oracle.graal.nodes.cfg.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.phases.graph.*; -import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; -import com.oracle.graal.phases.graph.ReentrantBlockIterator.LoopInfo; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.virtual.nodes.*; -import com.oracle.graal.virtual.phases.ea.BlockState.ReadCacheEntry; -import com.oracle.graal.virtual.phases.ea.EffectList.Effect; -public class PartialEscapeClosure extends PartialEscapeAnalysisPhase.Closure { +public abstract class PartialEscapeClosure> extends EffectsClosure { public static final DebugMetric METRIC_MATERIALIZATIONS = Debug.metric("Materializations"); public static final DebugMetric METRIC_MATERIALIZATIONS_PHI = Debug.metric("MaterializationsPhi"); @@ -61,143 +52,63 @@ public static final DebugMetric METRIC_MEMORYCHECKOINT = Debug.metric("MemoryCheckpoint"); private final NodeBitMap usages; - private final SchedulePhase schedule; - - private final BlockMap blockEffects; - private final IdentityHashMap loopMergeEffects = new IdentityHashMap<>(); - private final VirtualizerToolImpl tool; - private final Map hints = new IdentityHashMap<>(); - private boolean changed; + /** + * Final subclass of PartialEscapeClosure, for performance and to make everything behave nicely + * with generics. + */ + public static final class Final extends PartialEscapeClosure { - public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) { - this.usages = schedule.getCFG().graph.createNodeBitMap(); - this.schedule = schedule; - this.tool = new VirtualizerToolImpl(usages, metaAccess, assumptions); - this.blockEffects = new BlockMap<>(schedule.getCFG()); - for (Block block : schedule.getCFG().getBlocks()) { - blockEffects.put(block, new GraphEffectList()); + public Final(SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) { + super(schedule, metaAccess, assumptions); + } + + @Override + protected PartialEscapeBlockState.Final getInitialState() { + return new PartialEscapeBlockState.Final(); + } + + @Override + protected PartialEscapeBlockState.Final cloneState(PartialEscapeBlockState.Final oldState) { + return new PartialEscapeBlockState.Final(oldState); } } - @SuppressWarnings("unchecked") - @Override - protected BlockT getInitialState() { - return (BlockT) new BlockState(); - } - - @Override - public boolean hasChanged() { - return changed; - } - - @Override - public void applyEffects() { - final StructuredGraph graph = schedule.getCFG().graph; - final ArrayList obsoleteNodes = new ArrayList<>(0); - BlockIteratorClosure closure = new BlockIteratorClosure() { - - @Override - protected Void getInitialState() { - return null; - } - - private void apply(GraphEffectList effects, Object context) { - if (!effects.isEmpty()) { - Debug.log(" ==== effects for %s", context); - for (Effect effect : effects) { - effect.apply(graph, obsoleteNodes); - if (effect.isVisible()) { - Debug.log(" %s", effect); - } - } - } - } - - @Override - protected Void processBlock(Block block, Void currentState) { - apply(blockEffects.get(block), block); - return currentState; - } - - @Override - protected Void merge(Block merge, List states) { - return null; - } - - @Override - protected Void cloneState(Void oldState) { - return oldState; - } - - @Override - protected List processLoop(Loop loop, Void initialState) { - LoopInfo info = ReentrantBlockIterator.processLoop(this, loop, initialState); - apply(loopMergeEffects.get(loop), loop); - return info.exitStates; - } - }; - ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock()); - assert VirtualUtil.assertNonReachable(graph, obsoleteNodes); + public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) { + super(schedule); + this.usages = schedule.getCFG().graph.createNodeBitMap(); + this.tool = new VirtualizerToolImpl(usages, metaAccess, assumptions); } public Map getHints() { return hints; } + /** + * @return true if the node was deleted, false otherwise + */ @Override - protected BlockT processBlock(Block block, BlockT state) { - GraphEffectList effects = blockEffects.get(block); - tool.setEffects(effects); - - VirtualUtil.trace("\nBlock: %s (", block); - List nodeList = schedule.getBlockToNodesMap().get(block); - - FixedWithNextNode lastFixedNode = null; - for (Node node : nodeList) { - boolean deleted; - boolean isMarked = usages.isMarked(node); - if (isMarked || node instanceof VirtualizableRoot) { - VirtualUtil.trace("[[%s]] ", node); - FixedNode nextFixedNode = lastFixedNode == null ? null : lastFixedNode.next(); - deleted = processNode((ValueNode) node, nextFixedNode, state, effects, isMarked); - } else { - VirtualUtil.trace("%s ", node); - deleted = false; - } - if (OptEarlyReadElimination.getValue()) { - if (!deleted && node instanceof MemoryCheckpoint) { - METRIC_MEMORYCHECKOINT.increment(); - MemoryCheckpoint checkpoint = (MemoryCheckpoint) node; - for (LocationIdentity identity : checkpoint.getLocationIdentities()) { - if (identity instanceof ResolvedJavaField) { - state.killReadCache((ResolvedJavaField) identity); - } else if (identity == ANY_LOCATION) { - state.killReadCache(); - } - } - } - } - if (node instanceof FixedWithNextNode) { - lastFixedNode = (FixedWithNextNode) node; - } + protected boolean processNode(Node node, BlockT state, GraphEffectList effects, FixedWithNextNode lastFixedNode) { + boolean isMarked = usages.isMarked(node); + if (isMarked || node instanceof VirtualizableRoot) { + VirtualUtil.trace("[[%s]] ", node); + FixedNode nextFixedNode = lastFixedNode == null ? null : lastFixedNode.next(); + return processNode((ValueNode) node, nextFixedNode, state, effects, isMarked); + } else { + VirtualUtil.trace("%s ", node); + return false; } - VirtualUtil.trace(")\n end state: %s\n", state); - return state; } private boolean processNode(final ValueNode node, FixedNode insertBefore, final BlockT state, final GraphEffectList effects, boolean isMarked) { - tool.reset(state, node, insertBefore); + tool.reset(state, node, insertBefore, effects); if (node instanceof Virtualizable) { ((Virtualizable) node).virtualize(tool); } if (tool.isDeleted()) { - if (!(node instanceof CommitAllocationNode || node instanceof AllocatedObjectNode)) { - changed = true; - } - return true; + return !(node instanceof CommitAllocationNode || node instanceof AllocatedObjectNode); } if (isMarked) { if (node instanceof StateSplit) { @@ -289,7 +200,7 @@ return false; } - private static void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore, GraphEffectList effects, DebugMetric metric) { + private static void ensureMaterialized(PartialEscapeBlockState state, ObjectState obj, FixedNode materializeBefore, GraphEffectList effects, DebugMetric metric) { assert obj != null; if (obj.getState() == EscapeState.Virtual) { metric.increment(); @@ -300,70 +211,13 @@ assert !obj.isVirtual(); } - private static void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj, GraphEffectList effects, DebugMetric metric) { + private static void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, PartialEscapeBlockState state, ObjectState obj, GraphEffectList effects, DebugMetric metric) { ensureMaterialized(state, obj, materializeBefore, effects, metric); effects.replaceFirstInput(usage, value, obj.getMaterializedValue()); } @Override - protected BlockT merge(Block merge, List states) { - assert blockEffects.get(merge).isEmpty(); - MergeProcessor processor = new MergeProcessor<>(merge, usages, blockEffects); - processor.merge(states); - blockEffects.get(merge).addAll(processor.mergeEffects); - blockEffects.get(merge).addAll(processor.afterMergeEffects); - return processor.newState; - - } - - @SuppressWarnings("unchecked") - @Override - protected BlockT cloneState(BlockState oldState) { - return (BlockT) oldState.cloneState(); - } - - @SuppressWarnings("unchecked") - @Override - protected List processLoop(Loop loop, BlockT initialState) { - BlockState loopEntryState = initialState; - BlockState lastMergedState = initialState; - MergeProcessor mergeProcessor = new MergeProcessor<>(loop.header, usages, blockEffects); - for (int iteration = 0; iteration < 10; iteration++) { - LoopInfo info = ReentrantBlockIterator.processLoop(this, loop, (BlockT) lastMergedState.cloneState()); - - List states = new ArrayList<>(); - states.add(initialState); - states.addAll(info.endStates); - mergeProcessor.merge(states); - - Debug.log("================== %s", loop.header); - Debug.log("%s", mergeProcessor.newState); - Debug.log("===== vs."); - Debug.log("%s", lastMergedState); - - if (mergeProcessor.newState.equivalentTo(lastMergedState)) { - blockEffects.get(loop.header).insertAll(mergeProcessor.mergeEffects, 0); - loopMergeEffects.put(loop, mergeProcessor.afterMergeEffects); - - assert info.exitStates.size() == loop.exits.size(); - for (int i = 0; i < loop.exits.size(); i++) { - BlockState exitState = info.exitStates.get(i); - assert exitState != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header; - processLoopExit((LoopExitNode) loop.exits.get(i).getBeginNode(), loopEntryState, exitState, blockEffects.get(loop.exits.get(i))); - } - - return info.exitStates; - } else { - lastMergedState = mergeProcessor.newState; - for (Block block : loop.blocks) { - blockEffects.get(block).clear(); - } - } - } - throw new GraalInternalError("too many iterations at %s", loop); - } - - private static void processLoopExit(LoopExitNode exitNode, BlockState initialState, BlockState exitState, GraphEffectList effects) { + protected void processLoopExit(LoopExitNode exitNode, BlockT initialState, BlockT exitState, GraphEffectList effects) { HashMap proxies = new HashMap<>(); for (ProxyNode proxy : exitNode.proxies()) { @@ -404,41 +258,25 @@ } } } - - for (Map.Entry entry : exitState.getReadCache().entrySet()) { - if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) { - ProxyNode proxy = new ProxyNode(exitState.getReadCache(entry.getKey().object, entry.getKey().identity), exitNode, PhiType.Value, null); - effects.addFloatingNode(proxy, "readCacheProxy"); - entry.setValue(proxy); - } - } } - private static class MergeProcessor { + @Override + protected MergeProcessor createMergeProcessor(Block merge) { + return new MergeProcessor(merge); + } - private final Block mergeBlock; - private final MergeNode merge; - private final NodeBitMap usages; - private final BlockMap blockEffects; - private final GraphEffectList mergeEffects; - private final GraphEffectList afterMergeEffects; + protected class MergeProcessor extends EffectsClosure.MergeProcessor { private final HashMap materializedPhis = new HashMap<>(); private final IdentityHashMap valuePhis = new IdentityHashMap<>(); private final IdentityHashMap valueObjectMergePhis = new IdentityHashMap<>(); private final IdentityHashMap valueObjectVirtuals = new IdentityHashMap<>(); - private BlockT newState; - public MergeProcessor(Block mergeBlock, NodeBitMap usages, BlockMap blockEffects) { - this.usages = usages; - this.mergeBlock = mergeBlock; - this.blockEffects = blockEffects; - this.merge = (MergeNode) mergeBlock.getBeginNode(); - this.mergeEffects = new GraphEffectList(); - this.afterMergeEffects = new GraphEffectList(); + public MergeProcessor(Block mergeBlock) { + super(mergeBlock); } - private PhiNode getCachedPhi(T virtual, Kind kind) { + protected PhiNode getCachedPhi(T virtual, Kind kind) { PhiNode result = materializedPhis.get(virtual); if (result == null) { result = new PhiNode(kind, merge); @@ -474,10 +312,9 @@ return result; } - @SuppressWarnings("unchecked") - private void merge(List states) { - newState = (BlockT) states.get(0).cloneEmptyState(); - newState.meetAliases(states); + @Override + protected void merge(List states) { + super.merge(states); /* * Iterative processing: Merging the materialized/virtual state of virtual objects can @@ -519,7 +356,7 @@ PhiNode materializedValuePhi = getCachedPhi(object, Kind.Object); mergeEffects.addFloatingNode(materializedValuePhi, "materializedPhi"); for (int i = 0; i < states.size(); i++) { - BlockState state = states.get(i); + PartialEscapeBlockState state = states.get(i); ObjectState obj = objStates[i]; materialized |= obj.isVirtual(); Block predecessor = mergeBlock.getPredecessors().get(i); @@ -578,8 +415,6 @@ } } } while (materialized); - - mergeReadCache(states); } private boolean processPhi(PhiNode phi, List states) { @@ -665,62 +500,5 @@ } return materialized; } - - private void mergeReadCache(List states) { - for (Map.Entry entry : states.get(0).readCache.entrySet()) { - ReadCacheEntry key = entry.getKey(); - ValueNode value = entry.getValue(); - boolean phi = false; - for (int i = 1; i < states.size(); i++) { - ValueNode otherValue = states.get(i).readCache.get(key); - if (otherValue == null) { - value = null; - phi = false; - break; - } - if (!phi && otherValue != value) { - phi = true; - } - } - if (phi) { - PhiNode phiNode = getCachedPhi(entry, value.kind()); - mergeEffects.addFloatingNode(phiNode, "mergeReadCache"); - for (int i = 0; i < states.size(); i++) { - afterMergeEffects.addPhiInput(phiNode, states.get(i).getReadCache(key.object, key.identity)); - } - newState.readCache.put(key, phiNode); - } else if (value != null) { - newState.readCache.put(key, value); - } - } - for (PhiNode phi : merge.phis()) { - if (phi.kind() == Kind.Object) { - for (Map.Entry entry : states.get(0).readCache.entrySet()) { - if (entry.getKey().object == phi.valueAt(0)) { - mergeReadCachePhi(phi, entry.getKey().identity, states); - } - } - - } - } - } - - private void mergeReadCachePhi(PhiNode phi, ResolvedJavaField identity, List states) { - ValueNode[] values = new ValueNode[phi.valueCount()]; - for (int i = 0; i < phi.valueCount(); i++) { - ValueNode value = states.get(i).getReadCache(phi.valueAt(i), identity); - if (value == null) { - return; - } - values[i] = value; - } - - PhiNode phiNode = getCachedPhi(new ReadCacheEntry(identity, phi), values[0].kind()); - mergeEffects.addFloatingNode(phiNode, "mergeReadCachePhi"); - for (int i = 0; i < values.length; i++) { - afterMergeEffects.addPhiInput(phiNode, values[i]); - } - newState.readCache.put(new ReadCacheEntry(identity, phi), phiNode); - } } } diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java Fri Jun 07 16:43:35 2013 +0200 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.virtual.phases.ea; + +import static com.oracle.graal.phases.GraalOptions.*; + +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.graph.*; +import com.oracle.graal.phases.schedule.*; +import com.oracle.graal.phases.tiers.*; + +public class PartialEscapePhase extends EffectsPhase { + + public PartialEscapePhase(boolean iterative, CanonicalizerPhase canonicalizer) { + super(iterative ? EscapeAnalysisIterations.getValue() : 1, canonicalizer); + } + + @Override + protected void run(StructuredGraph graph, PhaseContext context) { + if (VirtualUtil.matches(graph, EscapeAnalyzeOnly.getValue())) { + boolean analyzableNodes = false; + for (Node node : graph.getNodes()) { + if (node instanceof VirtualizableAllocation) { + analyzableNodes = true; + break; + } + } + if (analyzableNodes) { + runAnalysis(graph, context); + } + } + } + + @Override + protected Closure createEffectsClosure(PhaseContext context, SchedulePhase schedule) { + return new PartialEscapeClosure.Final(schedule, context.getRuntime(), context.getAssumptions()); + } + + public static Map getHints(StructuredGraph graph) { + NodesToDoubles probabilities = new ComputeProbabilityClosure(graph).apply(); + Map hints = null; + for (CommitAllocationNode commit : graph.getNodes(CommitAllocationNode.class)) { + double sum = 0; + double invokeSum = 0; + for (Node commitUsage : commit.usages()) { + for (Node usage : commitUsage.usages()) { + if (usage instanceof FixedNode) { + sum += probabilities.get((FixedNode) usage); + } else { + if (usage instanceof MethodCallTargetNode) { + invokeSum += probabilities.get(((MethodCallTargetNode) usage).invoke().asNode()); + } + for (Node secondLevelUage : usage.usages()) { + if (secondLevelUage instanceof FixedNode) { + sum += probabilities.get(((FixedNode) secondLevelUage)); + } + } + } + } + } + // TODO(lstadler) get rid of this magic number + if (sum > 100 && invokeSum > 0) { + for (Node commitUsage : commit.usages()) { + for (Node usage : commitUsage.usages()) { + if (usage instanceof MethodCallTargetNode) { + if (hints == null) { + hints = new HashMap<>(); + } + Invoke invoke = ((MethodCallTargetNode) usage).invoke(); + hints.put(invoke, sum / invokeSum); + } + } + } + } + } + return hints; + } +} diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java Fri Jun 07 16:43:35 2013 +0200 @@ -111,7 +111,7 @@ } } - static boolean matches(StructuredGraph graph, String filter) { + public static boolean matches(StructuredGraph graph, String filter) { if (filter != null) { if (filter.startsWith("~")) { ResolvedJavaMethod method = graph.method(); diff -r 671bcaf13017 -r eef9281ec13b graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Fri Jun 07 14:27:04 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Fri Jun 07 16:43:35 2013 +0200 @@ -39,7 +39,6 @@ private final NodeBitMap usages; private final MetaAccessProvider metaAccess; private final Assumptions assumptions; - private GraphEffectList effects; VirtualizerToolImpl(NodeBitMap usages, MetaAccessProvider metaAccess, Assumptions assumptions) { this.usages = usages; @@ -48,9 +47,10 @@ } private boolean deleted; - private BlockState state; + private PartialEscapeBlockState state; private ValueNode current; private FixedNode position; + private GraphEffectList effects; @Override public MetaAccessProvider getMetaAccessProvider() { @@ -62,15 +62,12 @@ return assumptions; } - public void setEffects(GraphEffectList effects) { - this.effects = effects; - } - - public void reset(BlockState newState, ValueNode newCurrent, FixedNode newPosition) { + public void reset(PartialEscapeBlockState newState, ValueNode newCurrent, FixedNode newPosition, GraphEffectList newEffects) { deleted = false; state = newState; current = newCurrent; position = newPosition; + effects = newEffects; } public boolean isDeleted() { @@ -136,7 +133,6 @@ @Override public void delete() { - assert current instanceof FixedWithNextNode; effects.deleteFixedNode((FixedWithNextNode) current); deleted = true; } @@ -189,26 +185,4 @@ } } } - - @Override - public void addReadCache(ValueNode object, ResolvedJavaField identity, ValueNode value) { - if (OptEarlyReadElimination.getValue()) { - state.addReadCache(object, identity, value); - } - } - - @Override - public ValueNode getReadCache(ValueNode object, ResolvedJavaField identity) { - if (OptEarlyReadElimination.getValue()) { - return state.getReadCache(object, identity); - } - return null; - } - - @Override - public void killReadCache(ResolvedJavaField identity) { - if (OptEarlyReadElimination.getValue()) { - state.killReadCache(identity); - } - } }