changeset 5632:4d0f01e9f31b

Added detailed test cases for the closed world analysis. Add support for ValueProxyNode, CheckCastNode. Fix modelling of arrays.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sat, 16 Jun 2012 02:19:38 +0200
parents f2d228de28d7
children bda2ebe1fc61
files graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/BigBangTest.java graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/HelloWorldTest.java graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/TestPrograms.java graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/test/helloworld/HelloWorldTestProgram.java graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BigBang.java graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageGenerator.java graal/com.oracle.graal.boot/src/com/oracle/graal/boot/UniverseExpansionOp.java graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ArrayTypeElement.java graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/CastElement.java graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/Element.java graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/InvokeElement.java graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/MethodElement.java graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/PhiElement.java graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ProxyElement.java
diffstat 14 files changed, 325 insertions(+), 89 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/BigBangTest.java	Sat Jun 16 02:19:38 2012 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.boot;
+
+import org.junit.*;
+
+public class BigBangTest {
+
+    @Test
+    public void helloWorldTest() {
+        BootImageGenerator generator = new BootImageGenerator();
+        generator.addEntryMethod(TestPrograms.class, "helloWorldTest");
+        Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{3, 118, 58, 21});
+    }
+
+    @Test
+    public void formattedOutputTest() {
+        BootImageGenerator generator = new BootImageGenerator();
+        generator.addEntryMethod(TestPrograms.class, "formattedOutputTest");
+        Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{15, 979, 346, 98});
+    }
+
+
+    @Test
+    public void newTest() {
+        BootImageGenerator generator = new BootImageGenerator();
+        generator.addEntryMethod(TestPrograms.class, "newTest");
+        Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{0, 3, 0, 0});
+    }
+
+
+    @Test
+    public void arraycopyTest() {
+        BootImageGenerator generator = new BootImageGenerator();
+        generator.addEntryMethod(TestPrograms.class, "arraycopyTest");
+        Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{2, 6, 0, 0});
+    }
+
+    @Test
+    public void arrayListTest() {
+        BootImageGenerator generator = new BootImageGenerator();
+        generator.addEntryMethod(TestPrograms.class, "arrayListTest");
+        Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{2, 20, 3, 2});
+    }
+}
--- a/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/HelloWorldTest.java	Sat Jun 16 02:17:44 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +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.boot;
-
-import com.oracle.graal.boot.test.helloworld.*;
-
-
-public class HelloWorldTest {
-    public static void main(String[] args) {
-        BootImageGenerator generator = new BootImageGenerator();
-        generator.addEntryMethod(HelloWorldTestProgram.class, "main", String[].class);
-        generator.printState();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/TestPrograms.java	Sat Jun 16 02:19:38 2012 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.boot;
+
+import java.util.*;
+
+public class TestPrograms {
+    public static void helloWorldTest() {
+        System.out.println("Hello world!");
+    }
+
+    public static void formattedOutputTest() {
+        System.out.printf("%s %s!", "Hello", "world");
+    }
+
+    @SuppressWarnings("unused")
+    public static void newTest() {
+        Integer x = new Integer(5);
+    }
+
+    public static void arraycopyTest() {
+        Object[] arr = new Object[1];
+        arr[0] = new TestObject();
+        TestObject[] newArr = Arrays.copyOf(arr, 1, TestObject[].class);
+        newArr[0].testMethod();
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void arrayListTest() {
+        ArrayList list = new ArrayList();
+        list.add(new TestObject());
+        TestObject[] newArr = (TestObject[]) list.toArray(new TestObject[0]);
+        newArr[0].testMethod();
+    }
+
+    public static class TestObject {
+        public void testMethod() {
+        }
+    }
+}
--- a/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/test/helloworld/HelloWorldTestProgram.java	Sat Jun 16 02:17:44 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +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.boot.test.helloworld;
-
-public class HelloWorldTestProgram {
-    public static void main(String[] args) {
-        System.out.println("Hello world!");
-    }
-}
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BigBang.java	Sat Jun 16 02:17:44 2012 +0200
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BigBang.java	Sat Jun 16 02:19:38 2012 +0200
@@ -35,7 +35,7 @@
 
 public class BigBang {
 
-    private static final int THREADS = 1;
+    private static final int THREADS = 4;
 
     private MetaAccessProvider metaAccessProvider;
     private int postedOperationCount;
@@ -83,20 +83,26 @@
             if (node instanceof PhiNode) {
                 PhiNode phiNode = (PhiNode) node;
                 resultElement = new PhiElement(phiNode);
+            } else if (node instanceof CheckCastNode) {
+                CheckCastNode checkCastNode = (CheckCastNode) node;
+                resultElement = new CastElement(checkCastNode);
+            } else if (node instanceof ValueProxyNode) {
+                ValueProxyNode proxyNode = (ValueProxyNode) node;
+                resultElement = new ProxyElement(proxyNode);
             } else if (node instanceof StoreFieldNode) {
                 StoreFieldNode storeFieldNode = (StoreFieldNode) node;
                 resultElement = getProcessedField(storeFieldNode.field());
             } else if (node instanceof StoreIndexedNode) {
                 StoreIndexedNode storeIndexedNode = (StoreIndexedNode) node;
                 if (storeIndexedNode.elementKind() == Kind.Object) {
-                    resultElement = getProcessedArrayType(storeIndexedNode.array().stamp().declaredType());
+                    resultElement = getProcessedArrayType(metaAccessProvider.getResolvedJavaType(Object[].class));
                 }
             } else if (node instanceof ReturnNode) {
                 ReturnNode returnNode = (ReturnNode) node;
                 ResolvedJavaMethod method = ((StructuredGraph) returnNode.graph()).method();
                 resultElement = getProcessedMethod(method);
             } else {
-                if (node instanceof FrameState || node instanceof MonitorEnterNode || node instanceof MonitorExitNode || node instanceof LoadFieldNode || node instanceof IsNullNode) {
+                if (node instanceof FrameState || node instanceof MonitorEnterNode || node instanceof MonitorExitNode || node instanceof LoadFieldNode || node instanceof IsNullNode || node instanceof InstanceOfNode) {
                     // OK.
                 } else {
                     System.out.println("Unknown sink - black hole? " + node);
@@ -123,7 +129,9 @@
     }
 
     public synchronized void registerSourceCallTargetNode(MethodCallTargetNode methodCallTargetNode) {
-        sinkMap.put(methodCallTargetNode, new InvokeElement(methodCallTargetNode));
+        InvokeElement invokeElement = new InvokeElement(methodCallTargetNode);
+        sinkMap.put(methodCallTargetNode, invokeElement);
+        invokeElement.expandStaticMethod(this);
     }
 
     public synchronized void registerSourceNode(Node node) {
@@ -133,7 +141,9 @@
             resultElement = getProcessedField(loadFieldNode.field());
         } else if (node instanceof LoadIndexedNode) {
             LoadIndexedNode loadIndexedNode = (LoadIndexedNode) node;
-            resultElement = getProcessedArrayType(loadIndexedNode.array().stamp().declaredType());
+            if (loadIndexedNode.kind() == Kind.Object) {
+                resultElement = getProcessedArrayType(metaAccessProvider.getResolvedJavaType(Object[].class));
+            }
         } else if (node instanceof LocalNode) {
             LocalNode localNode = (LocalNode) node;
             if (localNode.kind() == Kind.Object) {
@@ -240,7 +250,7 @@
 
     }
 
-    public synchronized void printState() {
+    public synchronized int[] printState() {
 
         int nativeMethodCount = 0;
         for (MethodElement methodElement : methodMap.values()) {
@@ -266,7 +276,9 @@
         int fieldCount = 0;
         for (FieldElement fieldElement : fieldMap.values()) {
             if (fieldElement.getUsageCount() > 0) {
-                System.out.println("Included field: " + fieldElement.getJavaField());
+                System.out.print("Included field: " + fieldElement.getJavaField() + " / ");
+                fieldElement.printSeenTypes();
+                System.out.println();
                 fieldCount++;
                 includedTypes.add(fieldElement.getJavaField().holder());
             }
@@ -280,5 +292,6 @@
         System.out.println("Number of included method: " + methodCount);
         System.out.println("Number of included fields: " + fieldCount);
         System.out.println("Number of included types: " + includedTypes.size());
+        return new int[]{nativeMethodCount, methodCount, fieldCount, includedTypes.size()};
     }
 }
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageGenerator.java	Sat Jun 16 02:17:44 2012 +0200
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageGenerator.java	Sat Jun 16 02:19:38 2012 +0200
@@ -54,9 +54,7 @@
         bigbang.finish();
     }
 
-
-    public void printState() {
-        System.out.println("State of boot image generation");
-        bigbang.printState();
+    public BigBang getBigBang() {
+        return bigbang;
     }
 }
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/UniverseExpansionOp.java	Sat Jun 16 02:17:44 2012 +0200
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/UniverseExpansionOp.java	Sat Jun 16 02:19:38 2012 +0200
@@ -22,9 +22,6 @@
  */
 package com.oracle.graal.boot;
 
-import com.oracle.graal.boot.*;
-
-
 
 public abstract class UniverseExpansionOp implements Runnable {
 
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ArrayTypeElement.java	Sat Jun 16 02:17:44 2012 +0200
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ArrayTypeElement.java	Sat Jun 16 02:19:38 2012 +0200
@@ -22,7 +22,13 @@
  */
 package com.oracle.graal.boot.meta;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.boot.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
 
 
 public class ArrayTypeElement extends Element {
@@ -36,6 +42,28 @@
 
     @Override
     public String toString() {
-        return javaType + super.toString();
+        return "arrayTypeElement: " + javaType;
+    }
+
+    @Override
+    protected void propagateTypesToUsage(BigBang bb, Node use, Set<ResolvedJavaType> set, Element element) {
+        LoadIndexedNode load = (LoadIndexedNode) use;
+        ResolvedJavaType declaredType = load.array().stamp().declaredType();
+        if (declaredType == null) {
+            System.out.println("FATAL error: Array access without declared type!");
+            System.out.println(load.array());
+            System.out.println(((StructuredGraph) load.graph()).method());
+            System.exit(-1);
+        }
+        ResolvedJavaType componentType = declaredType.componentType();
+        Set<ResolvedJavaType> newSet = new HashSet<>();
+        for (ResolvedJavaType myType : set) {
+            if (myType.isSubtypeOf(componentType)) {
+                newSet.add(myType);
+            }
+        }
+        if (newSet.size() > 0) {
+            super.propagateTypesToUsage(bb, use, newSet, element);
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/CastElement.java	Sat Jun 16 02:19:38 2012 +0200
@@ -0,0 +1,61 @@
+/*
+ * 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.boot.meta;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.boot.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.java.*;
+
+
+public class CastElement extends Element {
+
+    private CheckCastNode checkCastNode;
+
+    public CastElement(CheckCastNode checkCastNode) {
+        super(checkCastNode.targetClass());
+        this.checkCastNode = checkCastNode;
+        this.usages.add(checkCastNode);
+    }
+
+    @Override
+    protected synchronized void unionTypes(BigBang bb, Node sourceNode, Set<ResolvedJavaType> newSeenTypes) {
+        Set<ResolvedJavaType> newSet = new HashSet<>();
+        // Filter through checkcast.
+        for (ResolvedJavaType type : newSeenTypes) {
+            if (type.isSubtypeOf(checkCastNode.targetClass())) {
+                newSet.add(type);
+            } else {
+                System.out.println("filtering " + type + " vs " + checkCastNode.targetClass());
+            }
+        }
+        super.unionTypes(bb, sourceNode, newSet);
+    }
+
+    @Override
+    public String toString() {
+        return "cast " + checkCastNode.targetClass();
+    }
+}
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/Element.java	Sat Jun 16 02:17:44 2012 +0200
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/Element.java	Sat Jun 16 02:19:38 2012 +0200
@@ -101,16 +101,27 @@
         }
     }
 
-    public static void propagateTypes(BigBang bb, Node n, Set<ResolvedJavaType> types) {
+    public void propagateTypes(BigBang bb, Node n, Set<ResolvedJavaType> types) {
         if (types.size() != 0) {
             Set<ResolvedJavaType> newSet = new HashSet<>(types);
             for (Node use : n.usages()) {
                 Element element = bb.getSinkElement(use, n);
                 assert element != null;
                 if (element != BLACK_HOLE) {
-                    element.postUnionTypes(bb, n, newSet);
+                    propagateTypesToUsage(bb, n, newSet, element);
                 }
             }
         }
     }
+
+    protected void propagateTypesToUsage(BigBang bb, Node use, Set<ResolvedJavaType> newSet, Element element) {
+        element.postUnionTypes(bb, use, newSet);
+    }
+
+
+    public synchronized void printSeenTypes() {
+        for (ResolvedJavaType type : seenTypes) {
+            System.out.print(type.name() + " ");
+        }
+    }
 }
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/InvokeElement.java	Sat Jun 16 02:17:44 2012 +0200
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/InvokeElement.java	Sat Jun 16 02:19:38 2012 +0200
@@ -47,7 +47,7 @@
     @Override
     protected synchronized void unionTypes(BigBang bb, Node sourceNode, Set<ResolvedJavaType> newSeenTypes) {
 
-        System.out.println("union invoke element " + this);
+        System.out.println("union invoke element " + this + " new types = " + newSeenTypes + " sourceNode= " + sourceNode);
         int index = 0;
         for (Node arg : methodCallTarget.arguments()) {
             if (arg == sourceNode) {
@@ -63,12 +63,22 @@
         return "Invoke[bci=" + methodCallTarget.invoke().stateAfter().method() + "," + methodCallTarget.targetMethod() + "]";
     }
 
+    public synchronized void expandStaticMethod(BigBang bb) {
+        if (methodCallTarget.isStatic()) {
+            ResolvedJavaMethod method = methodCallTarget.targetMethod();
+            concreteTargets.add(method);
+            MethodElement processedMethod = bb.getProcessedMethod(method);
+            processedMethod.postParseGraph(bb);
+        }
+    }
+
     private void unionTypes(BigBang bb, @SuppressWarnings("unused") Node sourceNode, Set<ResolvedJavaType> newSeenTypes, int index) {
         if (index == 0 && !methodCallTarget.isStatic()) {
             for (ResolvedJavaType type : newSeenTypes) {
                 if (seenTypes.add(type)) {
                     // There is a new receiver type!
                     ResolvedJavaMethod method = type.resolveMethodImpl(methodCallTarget.targetMethod());
+                    System.out.println("resolved method " + method + " for type " + type + " and method " + methodCallTarget.targetMethod());
                     if (method == null) {
                         System.out.println("!!! type = " + type + " / " + methodCallTarget.targetMethod());
                     }
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/MethodElement.java	Sat Jun 16 02:17:44 2012 +0200
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/MethodElement.java	Sat Jun 16 02:19:38 2012 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.boot.*;
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.java.GraphBuilderConfiguration.*;
@@ -79,13 +80,17 @@
         }.post(bb);
     }
 
-    protected synchronized void parseGraph(final BigBang bb) {
-        if (graph != null) {
-            // Graph already exists => quit operation.
-            return;
+    protected void parseGraph(final BigBang bb) {
+        StructuredGraph newGraph = null;
+        synchronized (this) {
+            if (graph != null) {
+                // Graph already exists => quit operation.
+                return;
+            }
+            newGraph = new StructuredGraph(resolvedJavaMethod);
+            this.graph = newGraph;
         }
-        StructuredGraph newGraph = new StructuredGraph(resolvedJavaMethod);
-        this.graph = newGraph;
+
         if (Modifier.isNative(resolvedJavaMethod.accessFlags())) {
             System.out.println("NATIVE METHOD " + resolvedJavaMethod);
             return;
@@ -95,6 +100,8 @@
         GraphBuilderConfiguration config = new GraphBuilderConfiguration(ResolvePolicy.Eager, null);
         GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(bb.getMetaAccess(), config, OptimisticOptimizations.NONE);
         graphBuilderPhase.apply(newGraph);
+        new PhiStampPhase().apply(newGraph);
+
         for (MethodCallTargetNode callTargetNode : newGraph.getNodes(MethodCallTargetNode.class)) {
             bb.registerSourceCallTargetNode(callTargetNode);
         }
@@ -107,7 +114,13 @@
             Set<ResolvedJavaType> types = new HashSet<>();
             types.add(newInstance.instanceClass());
             System.out.println("propagate new instance " + newInstance + ", " + newInstance.instanceClass());
-            Element.propagateTypes(bb, newInstance, types);
+            for (Node use : newInstance.usages()) {
+                Element element = bb.getSinkElement(use, newInstance);
+                assert element != null;
+                if (element != BLACK_HOLE) {
+                    element.postUnionTypes(bb, newInstance, types);
+                }
+            }
         }
     }
 
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/PhiElement.java	Sat Jun 16 02:17:44 2012 +0200
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/PhiElement.java	Sat Jun 16 02:19:38 2012 +0200
@@ -32,10 +32,11 @@
     public PhiElement(PhiNode phi) {
         super(null);
         this.phi = phi;
+        usages.add(phi);
     }
 
     @Override
     public String toString() {
-        return "phi " + phi + super.toString();
+        return "phi " + phi;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ProxyElement.java	Sat Jun 16 02:19:38 2012 +0200
@@ -0,0 +1,42 @@
+/*
+ * 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.boot.meta;
+
+import com.oracle.graal.nodes.*;
+
+
+public class ProxyElement extends Element {
+
+    private ValueProxyNode proxy;
+
+    public ProxyElement(ValueProxyNode proxy) {
+        super(null);
+        this.proxy = proxy;
+        usages.add(proxy);
+    }
+
+    @Override
+    public String toString() {
+        return "value proxy " + proxy;
+    }
+}