changeset 7016:05e03daa8645

Merge.
author Doug Simon <doug.simon@oracle.com>
date Fri, 23 Nov 2012 15:30:48 +0100
parents 62818f156081 (current diff) 7e12f1d11a5d (diff)
children 70bff0fa64b1
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java
diffstat 13 files changed, 164 insertions(+), 204 deletions(-) [+]
line wrap: on
line diff
--- 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);
+        }
     }
 }
--- 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<StructuredGraph>() {
-            @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);
+        }
     }
 }
--- 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);
--- 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()));
+        }
+    }
 }
--- 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;
--- 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;
     }
--- 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);
 }
--- 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();
-
-}
--- 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) {
--- 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) {
--- 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);
+            }
         }
     }
 
--- 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);
                     }
--- 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);