# HG changeset patch # User Doug Simon # Date 1353681048 -3600 # Node ID 05e03daa8645db490ce351027a32f98ac04aba17 # Parent 62818f15608114c476f3af5a02d0d454c032986e# Parent 7e12f1d11a5df767990c41c7b9f0f2d354607501 Merge. diff -r 62818f156081 -r 05e03daa8645 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 Nov 23 15:30:00 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Fri Nov 23 15:30:48 2012 +0100 @@ -22,17 +22,17 @@ */ package com.oracle.graal.compiler.test.ea; -import junit.framework.Assert; +import junit.framework.*; import org.junit.Test; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; -import com.oracle.graal.debug.*; 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.virtual.nodes.*; import com.oracle.graal.virtual.phases.ea.*; /** @@ -43,46 +43,42 @@ @Test public void test1() { - test("test1Snippet", Constant.forInt(101)); + testEscapeAnalysis("test1Snippet", Constant.forInt(101), false); } - @SuppressWarnings("all") - public static int test1Snippet(int a) { + public static int test1Snippet() { Integer x = new Integer(101); return x.intValue(); } @Test public void test2() { - test("test2Snippet", Constant.forInt(0)); + testEscapeAnalysis("test2Snippet", Constant.forInt(0), false); } - @SuppressWarnings("all") - public static int test2Snippet(int a) { + public static int test2Snippet() { Integer[] x = new Integer[0]; return x.length; } @Test public void test3() { - test("test3Snippet", Constant.forObject(null)); + testEscapeAnalysis("test3Snippet", Constant.forObject(null), false); } - @SuppressWarnings("all") - public static Object test3Snippet(int a) { + public static Object test3Snippet() { Integer[] x = new Integer[1]; return x[0]; } @Test public void testMonitor() { - test("testMonitorSnippet", Constant.forInt(0)); + testEscapeAnalysis("testMonitorSnippet", Constant.forInt(0), false); } private static native void notInlineable(); - @SuppressWarnings("all") - public static int testMonitorSnippet(int a) { + public static int testMonitorSnippet() { Integer x = new Integer(0); Integer[] y = new Integer[0]; Integer[] z = new Integer[1]; @@ -98,14 +94,13 @@ @Test public void testMonitor2() { - test("testMonitor2Snippet", Constant.forInt(0)); + testEscapeAnalysis("testMonitor2Snippet", Constant.forInt(0), false); } /** * This test case differs from the last one in that it requires inlining within a synchronized region. */ - @SuppressWarnings("all") - public static int testMonitor2Snippet(int a) { + public static int testMonitor2Snippet() { Integer x = new Integer(0); Integer[] y = new Integer[0]; Integer[] z = new Integer[1]; @@ -121,7 +116,7 @@ @Test public void testMerge() { - test("testMerge1Snippet", Constant.forInt(0)); + testEscapeAnalysis("testMerge1Snippet", Constant.forInt(0), true); } public static class TestObject { @@ -149,7 +144,7 @@ @Test public void testSimpleLoop() { - test("testSimpleLoopSnippet", Constant.forInt(1)); + testEscapeAnalysis("testSimpleLoopSnippet", Constant.forInt(1), false); } public int testSimpleLoopSnippet(int a) { @@ -160,37 +155,59 @@ return obj.x; } - private void test(final String snippet, final Constant expectedResult) { - Debug.scope("EscapeAnalysisTest", new DebugDumpScope(snippet), new Runnable() { - public void run() { - StructuredGraph graph = parse(snippet); - for (Invoke n : graph.getInvokes()) { - n.node().setProbability(100000); - } + public static class TestObject2 { + Object o; + public TestObject2(Object o) { + this.o = o; + } + } + + @Test + public void testCheckCast() { + testEscapeAnalysis("testCheckCastSnippet", Constant.forObject(TestObject2.class), false); + } + + public Object testCheckCastSnippet() { + TestObject2 obj = new TestObject2(TestObject2.class); + TestObject2 obj2 = new TestObject2(obj); + return ((TestObject2) obj2.o).o; + } + + @Test + public void testInstanceOf() { + ReturnNode returnNode = testEscapeAnalysis("testInstanceOfSnippet", null, false); + ValueNode result = returnNode.result(); + Assert.assertTrue(result instanceof MaterializeNode); + Assert.assertEquals(Constant.TRUE, ((MaterializeNode) result).condition().asConstant()); + } - new InliningPhase(null, runtime(), null, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new DeadCodeEliminationPhase().apply(graph); - Debug.dump(graph, "Graph"); - new PartialEscapeAnalysisPhase(null, runtime(), null).apply(graph); - new CullFrameStatesPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); - Debug.dump(graph, "Graph"); - int retCount = 0; - for (ReturnNode ret : graph.getNodes(ReturnNode.class)) { - Assert.assertTrue(ret.result().isConstant()); - Assert.assertEquals(ret.result().asConstant(), expectedResult); - retCount++; - } - Assert.assertEquals(1, retCount); - int newInstanceCount = 0; - for (@SuppressWarnings("unused") NewInstanceNode n : graph.getNodes(NewInstanceNode.class)) { - newInstanceCount++; - } - for (@SuppressWarnings("unused") NewObjectArrayNode n : graph.getNodes(NewObjectArrayNode.class)) { - newInstanceCount++; - } - Assert.assertEquals(0, newInstanceCount); + public boolean testInstanceOfSnippet() { + TestObject2 obj = new TestObject2(TestObject2.class); + TestObject2 obj2 = new TestObject2(obj); + return obj2.o instanceof TestObject2; + } + + private ReturnNode testEscapeAnalysis(String snippet, Constant expectedConstantResult, boolean iterativeEscapeAnalysis) { + StructuredGraph graph = parse(snippet); + try { + for (Invoke n : graph.getInvokes()) { + n.node().setProbability(100000); } - }); + + new InliningPhase(null, runtime(), null, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new DeadCodeEliminationPhase().apply(graph); + new PartialEscapeAnalysisPhase(null, runtime(), null, iterativeEscapeAnalysis).apply(graph); + Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count()); + ReturnNode returnNode = graph.getNodes(ReturnNode.class).first(); + if (expectedConstantResult != null) { + Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant()); + Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant()); + } + int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewObjectArrayNode.class).count() + graph.getNodes(MaterializeObjectNode.class).count(); + Assert.assertEquals(0, newInstanceCount); + return returnNode; + } catch (AssertionFailedError t) { + throw new RuntimeException(t.getMessage() + "\n" + getCanonicalGraphString(graph), t); + } } } diff -r 62818f156081 -r 05e03daa8645 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 Nov 23 15:30:00 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Fri Nov 23 15:30:48 2012 +0100 @@ -22,14 +22,12 @@ */ package com.oracle.graal.compiler.test.ea; -import java.util.concurrent.*; - +import junit.framework.*; import junit.framework.Assert; import org.junit.Test; import com.oracle.graal.compiler.test.*; -import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; @@ -145,26 +143,22 @@ } private StructuredGraph processMethod(final String snippet) { - return Debug.scope(getClass().getSimpleName(), new Callable() { - @Override - public StructuredGraph call() throws Exception { - StructuredGraph graph = parse(snippet); - new ComputeProbabilityPhase().apply(graph); - for (Invoke n : graph.getInvokes()) { - n.node().setProbability(100000); - } - new InliningPhase(null, runtime(), null, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); -// TypeSystemTest.outputGraph(graph, "before EscapeAnalysis " + snippet); - new PartialEscapeAnalysisPhase(null, runtime(), null).apply(graph); -// TypeSystemTest.outputGraph(graph, "after EscapeAnalysis " + snippet); - new CullFrameStatesPhase().apply(graph); - new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); -// TypeSystemTest.outputGraph(graph, "after CullFrameStates " + snippet); - return graph; + StructuredGraph graph = parse(snippet); + try { + new ComputeProbabilityPhase().apply(graph); + for (Invoke n : graph.getInvokes()) { + n.node().setProbability(100000); } - }); + new InliningPhase(null, runtime(), null, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new DeadCodeEliminationPhase().apply(graph); + new CanonicalizerPhase(null, runtime(), null).apply(graph); + new PartialEscapeAnalysisPhase(null, runtime(), null, false).apply(graph); + new CullFrameStatesPhase().apply(graph); + new DeadCodeEliminationPhase().apply(graph); + new CanonicalizerPhase(null, runtime(), null).apply(graph); + return graph; + } catch (AssertionFailedError t) { + throw new RuntimeException(t.getMessage() + "\n" + getCanonicalGraphString(graph), t); + } } } diff -r 62818f156081 -r 05e03daa8645 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 Nov 23 15:30:00 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Fri Nov 23 15:30:48 2012 +0100 @@ -153,7 +153,7 @@ } if (GraalOptions.PartialEscapeAnalysis && !plan.isPhaseDisabled(PartialEscapeAnalysisPhase.class)) { - new PartialEscapeAnalysisPhase(target, runtime, assumptions).apply(graph); + new PartialEscapeAnalysisPhase(target, runtime, assumptions, true).apply(graph); } if (GraalOptions.OptLoopTransform) { new LoopTransformHighPhase().apply(graph); diff -r 62818f156081 -r 05e03daa8645 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Fri Nov 23 15:30:00 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Fri Nov 23 15:30:48 2012 +0100 @@ -28,11 +28,12 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.virtual.*; /** * The {@code InstanceOfNode} represents an instanceof test. */ -public final class InstanceOfNode extends BooleanNode implements Canonicalizable, Lowerable, LIRLowerable { +public final class InstanceOfNode extends BooleanNode implements Canonicalizable, Lowerable, LIRLowerable, Virtualizable { @Input private ValueNode object; private final ResolvedJavaType type; @@ -129,4 +130,12 @@ } return super.verify(); } + + @Override + public void virtualize(VirtualizerTool tool) { + VirtualObjectNode virtual = tool.getVirtualState(object()); + if (virtual != null) { + tool.replaceWithValue(ConstantNode.forBoolean(virtual.type().isSubtypeOf(type()), graph())); + } + } } diff -r 62818f156081 -r 05e03daa8645 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Fri Nov 23 15:30:00 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Fri Nov 23 15:30:48 2012 +0100 @@ -105,32 +105,17 @@ } @Override - public EscapeOp getEscapeOp() { + public ObjectDesc[] getAllocations(long nextVirtualId, MetaAccessProvider metaAccess) { if (length().asConstant() != null) { final int constantLength = length().asConstant().asInt(); if (constantLength >= 0 && constantLength < MaximumEscapeAnalysisArrayLength) { - return new EscapeOp() { - - @Override - public ValueNode[] fieldState() { - ValueNode[] state = new ValueNode[constantLength]; - ConstantNode defaultForKind = constantLength == 0 ? null : ConstantNode.defaultForKind(elementType().getKind(), graph()); - for (int i = 0; i < constantLength; i++) { - state[i] = defaultForKind; - } - return state; - } - - @Override - public VirtualObjectNode virtualObject(long virtualId) { - return new VirtualArrayNode(virtualId, elementType, constantLength); - } - - @Override - public int lockCount() { - return 0; - } - }; + ValueNode[] state = new ValueNode[constantLength]; + ConstantNode defaultForKind = constantLength == 0 ? null : ConstantNode.defaultForKind(elementType().getKind(), graph()); + for (int i = 0; i < constantLength; i++) { + state[i] = defaultForKind; + } + VirtualObjectNode virtualObject = new VirtualArrayNode(nextVirtualId, elementType, constantLength); + return new ObjectDesc[]{new ObjectDesc(virtualObject, state, 0)}; } } return null; diff -r 62818f156081 -r 05e03daa8645 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Fri Nov 23 15:30:00 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Fri Nov 23 15:30:48 2012 +0100 @@ -82,31 +82,16 @@ } @Override - public EscapeOp getEscapeOp() { + public ObjectDesc[] getAllocations(long nextVirtualId, MetaAccessProvider metaAccess) { if (instanceClass != null) { assert !instanceClass().isArrayClass(); - final ResolvedJavaField[] fields = instanceClass().getInstanceFields(true); - return new EscapeOp() { - - @Override - public ValueNode[] fieldState() { - ValueNode[] state = new ValueNode[fields.length]; - for (int i = 0; i < state.length; i++) { - state[i] = ConstantNode.defaultForKind(fields[i].getType().getKind(), graph()); - } - return state; - } - - @Override - public VirtualObjectNode virtualObject(long virtualId) { - return new VirtualInstanceNode(virtualId, instanceClass(), fields); - } - - @Override - public int lockCount() { - return 0; - } - }; + ResolvedJavaField[] fields = instanceClass().getInstanceFields(true); + ValueNode[] state = new ValueNode[fields.length]; + for (int i = 0; i < state.length; i++) { + state[i] = ConstantNode.defaultForKind(fields[i].getType().getKind(), graph()); + } + VirtualObjectNode virtualObject = new VirtualInstanceNode(nextVirtualId, instanceClass(), fields); + return new ObjectDesc[]{new ObjectDesc(virtualObject, state, 0)}; } return null; } diff -r 62818f156081 -r 05e03daa8645 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeAnalyzable.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeAnalyzable.java Fri Nov 23 15:30:00 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeAnalyzable.java Fri Nov 23 15:30:48 2012 +0100 @@ -22,7 +22,24 @@ */ package com.oracle.graal.nodes.spi; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.virtual.*; + public interface EscapeAnalyzable { - EscapeOp getEscapeOp(); + public static class ObjectDesc { + + public final VirtualObjectNode virtualObject; + public final ValueNode[] entryState; + public final int lockCount; + + public ObjectDesc(VirtualObjectNode virtualObject, ValueNode[] entryState, int lockCount) { + this.virtualObject = virtualObject; + this.entryState = entryState; + this.lockCount = lockCount; + } + } + + ObjectDesc[] getAllocations(long nextVirtualId, MetaAccessProvider metaAccess); } diff -r 62818f156081 -r 05e03daa8645 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java Fri Nov 23 15:30:00 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/* - * Copyright (c) 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.nodes.spi; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.virtual.*; - -public abstract class EscapeOp { - - /** - * Returns the initial value of all fields. - */ - public abstract ValueNode[] fieldState(); - - public abstract VirtualObjectNode virtualObject(long virtualId); - - public abstract int lockCount(); - -} diff -r 62818f156081 -r 05e03daa8645 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Fri Nov 23 15:30:00 2012 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Fri Nov 23 15:30:48 2012 +0100 @@ -937,13 +937,8 @@ returnDuplicate.replaceAndDelete(n); } - invoke.node().clearInputs(); invoke.node().replaceAtUsages(null); GraphUtil.killCFG(invoke.node()); - - if (stateAfter.usages().isEmpty()) { - stateAfter.safeDelete(); - } } public static void receiverNullCheck(Invoke invoke) { diff -r 62818f156081 -r 05e03daa8645 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java Fri Nov 23 15:30:00 2012 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java Fri Nov 23 15:30:48 2012 +0100 @@ -101,27 +101,11 @@ } @Override - public EscapeOp getEscapeOp() { - if (!shouldRevirtualize(this)) { - return null; + public ObjectDesc[] getAllocations(long nextVirtualId, MetaAccessProvider metaAccess) { + if (shouldRevirtualize(this)) { + return new ObjectDesc[] {new ObjectDesc(virtualObject, values.toArray(new ValueNode[values.size()]), lockCount)}; } - return new EscapeOp() { - - @Override - public ValueNode[] fieldState() { - return values.toArray(new ValueNode[values.size()]); - } - - @Override - public VirtualObjectNode virtualObject(long virtualId) { - return virtualObject; - } - - @Override - public int lockCount() { - return lockCount; - } - }; + return null; } private boolean shouldRevirtualize(MaterializeObjectNode materializeObjectNode) { diff -r 62818f156081 -r 05e03daa8645 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 Nov 23 15:30:00 2012 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java Fri Nov 23 15:30:48 2012 +0100 @@ -158,8 +158,10 @@ void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node, NodeBitMap usages) { objectAliases.put(node, virtual); - for (Node usage : node.usages()) { - markVirtualUsages(usage, usages); + if (node.isAlive()) { + for (Node usage : node.usages()) { + markVirtualUsages(usage, usages); + } } } diff -r 62818f156081 -r 05e03daa8645 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 Nov 23 15:30:00 2012 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Fri Nov 23 15:30:48 2012 +0100 @@ -40,11 +40,13 @@ private final TargetDescription target; private final MetaAccessProvider runtime; private final Assumptions assumptions; + private final boolean iterative; - public PartialEscapeAnalysisPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) { + public PartialEscapeAnalysisPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, boolean iterative) { this.target = target; this.runtime = runtime; this.assumptions = assumptions; + this.iterative = iterative; } public static final void trace(String format, Object... obj) { @@ -87,6 +89,9 @@ assert noObsoleteNodes(graph, obsoleteNodes); new DeadCodeEliminationPhase().apply(graph); + if (!iterative) { + return; + } if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } diff -r 62818f156081 -r 05e03daa8645 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 Nov 23 15:30:00 2012 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Fri Nov 23 15:30:48 2012 +0100 @@ -36,6 +36,7 @@ import com.oracle.graal.nodes.VirtualState.NodeClosure; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.spi.EscapeAnalyzable.ObjectDesc; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.graph.*; @@ -71,10 +72,12 @@ private int virtualIds = 0; private final VirtualizerToolImpl tool; + private final MetaAccessProvider metaAccess; public PartialEscapeClosure(NodeBitMap usages, SchedulePhase schedule, MetaAccessProvider metaAccess) { this.usages = usages; this.schedule = schedule; + this.metaAccess = metaAccess; tool = new VirtualizerToolImpl(effects, usages, metaAccess); } @@ -93,29 +96,32 @@ FixedWithNextNode lastFixedNode = null; for (Node node : nodeList) { - EscapeOp op = null; + ObjectDesc[] newAllocations = null; if (node instanceof EscapeAnalyzable) { - op = ((EscapeAnalyzable) node).getEscapeOp(); + newAllocations = ((EscapeAnalyzable) node).getAllocations(virtualIds, metaAccess); } - if (op != null) { + if (newAllocations != null) { trace("{{%s}} ", node); - VirtualObjectNode virtualObject = op.virtualObject(virtualIds); - if (virtualObject.isAlive()) { - reusedVirtualObjects.add(virtualObject); + for (ObjectDesc desc : newAllocations) { + VirtualObjectNode virtualObject = desc.virtualObject; + if (virtualObject.isAlive()) { + reusedVirtualObjects.add(virtualObject); + state.addAndMarkAlias(virtualObject, virtualObject, usages); + } else { + effects.addFloatingNode(virtualObject); + } + ValueNode[] fieldState = desc.entryState; + for (int i = 0; i < fieldState.length; i++) { + fieldState[i] = state.getScalarAlias(fieldState[i]); + } + state.addObject(virtualObject, new ObjectState(virtualObject, fieldState, desc.lockCount)); state.addAndMarkAlias(virtualObject, virtualObject, usages); - } else { - effects.addFloatingNode(virtualObject); } - ValueNode[] fieldState = op.fieldState(); - for (int i = 0; i < fieldState.length; i++) { - fieldState[i] = state.getScalarAlias(fieldState[i]); - } - state.addObject(virtualObject, new ObjectState(virtualObject, fieldState, op.lockCount())); - state.addAndMarkAlias(virtualObject, (ValueNode) node, usages); + state.addAndMarkAlias(newAllocations[0].virtualObject, (ValueNode) node, usages); effects.deleteFixedNode((FixedWithNextNode) node); - virtualIds++; - metricAllocationRemoved.increment(); + metricAllocationRemoved.add(newAllocations.length); + virtualIds += newAllocations.length; } else { if (usages.isMarked(node)) { trace("[[%s]] ", node);