changeset 5641:731789427441

Merge.
author Lukas Stadler <lukas.stadler@jku.at>
date Mon, 18 Jun 2012 10:07:33 +0200
parents 8e098bf83c95 (current diff) a82376ebaaa9 (diff)
children 83236169ea42 f53a347eae93 1cfa35d467de
files graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/HelloWorldTest.java graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/test/helloworld/HelloWorldTestProgram.java
diffstat 52 files changed, 2090 insertions(+), 131 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java	Mon Jun 18 10:07:33 2012 +0200
@@ -47,6 +47,13 @@
     Constant constantValue(Constant receiver);
 
     /**
+     * Gets the current value of the field if available.
+     * @param receiver object from which this field's value is to be read. This value is ignored if this field is static.
+     * @return the value of this field or {@code null} if the value is not available (e.g., because the field holder is not yet initialized).
+     */
+    Constant getValue(Constant receiver);
+
+    /**
      * Gets the holder of this field as a compiler-runtime interface type.
      * @return the holder of this field
      */
--- a/graal/com.oracle.graal.api/src/com/oracle/graal/api/Graal.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.api/src/com/oracle/graal/api/Graal.java	Mon Jun 18 10:07:33 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.api;
 
-
 public class Graal {
 
     private static GraalRuntime runtime;
@@ -49,4 +48,12 @@
             };
         }
     }
+
+    public static <T> T getRequiredCapability(Class<T> clazz) {
+        T t = getRuntime().getCapability(clazz);
+        if (t == null) {
+            throw new IllegalAccessError("Runtime does not expose required capability " + clazz.getName());
+        }
+        return t;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/BigBangTest.java	Mon Jun 18 10:07:33 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});
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/BootImageClassLoaderTest.java	Mon Jun 18 10:07:33 2012 +0200
@@ -0,0 +1,79 @@
+/*
+ * 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.lang.reflect.*;
+
+import org.junit.*;
+
+
+public class BootImageClassLoaderTest {
+
+    @Test
+    public void test() throws ClassNotFoundException, IllegalArgumentException, IllegalAccessException, SecurityException {
+
+        TestClassB.x = 1;
+        BootImageClassLoader l = new BootImageClassLoader();
+
+        // Assert that the class definition is really duplicated.
+        Class<?> bClass = Class.forName(TestClassB.class.getCanonicalName(), true, l);
+        Assert.assertNotSame(TestClassB.class, bClass);
+
+        // Assert that the class definition is not duplicated more than once.
+        Assert.assertSame(bClass, l.convert(TestClassB.class));
+
+        // Set field x such that it is used by the subsequent static initializer for TestClassA.
+        Field bField = bClass.getFields()[0];
+        bField.setAccessible(true);
+        bField.set(null, 2);
+
+        // Assert that the class definition is duplicated.
+        Class<?> aClass = l.convert(TestClassA.class);
+        Assert.assertNotSame(TestClassA.class, aClass);
+
+        // Assert that the original version of TestClassA was initialized correctly.
+        Assert.assertEquals(1, TestClassA.x);
+
+        // Assert that the duplicated version of TestClassA was initialized correctly.
+        Field aField = aClass.getFields()[0];
+        aField.setAccessible(true);
+        Assert.assertEquals(2, aField.getInt(null));
+
+        // Assert that system classes are not duplicated.
+        Assert.assertSame(Object.class, l.convert(Object.class));
+        Assert.assertSame(Object.class, Class.forName(Object.class.getCanonicalName(), true, l));
+    }
+
+}
+
+class TestClassA {
+    public static int x;
+
+    static {
+        x = TestClassB.x;
+    }
+}
+
+class TestClassB {
+    public static int x;
+}
--- a/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/HelloWorldTest.java	Fri Jun 15 15:59:43 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +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;
-
-
-public class HelloWorldTest {
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/TestPrograms.java	Mon Jun 18 10:07:33 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	Fri Jun 15 15:59:43 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +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!");
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BigBang.java	Mon Jun 18 10:07:33 2012 +0200
@@ -0,0 +1,297 @@
+/*
+ * 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.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.boot.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
+
+public class BigBang {
+
+    private static final int THREADS = 4;
+
+    private MetaAccessProvider metaAccessProvider;
+    private int postedOperationCount;
+
+    // Mappings from Graal IR and Graal meta-data to element instances.
+    private Map<Node, Element> sinkMap = new IdentityHashMap<>();
+    private Map<ResolvedJavaField, FieldElement> fieldMap = new IdentityHashMap<>();
+    private Map<ResolvedJavaMethod, MethodElement> methodMap = new IdentityHashMap<>();
+    private Map<ResolvedJavaType, ArrayTypeElement> arrayTypeMap = new IdentityHashMap<>();
+
+    // Processing queue.
+    private ThreadPoolExecutor executor = new ThreadPoolExecutor(THREADS, THREADS, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), Executors.defaultThreadFactory());
+
+    public BigBang(MetaAccessProvider metaAccessProvider) {
+        this.metaAccessProvider = metaAccessProvider;
+    }
+
+    public synchronized FieldElement getProcessedField(ResolvedJavaField field) {
+        assert field != null;
+        if (!fieldMap.containsKey(field)) {
+            fieldMap.put(field, new FieldElement(field));
+        }
+        return fieldMap.get(field);
+    }
+
+    public synchronized MethodElement getProcessedMethod(ResolvedJavaMethod method) {
+        assert method != null;
+        if (!methodMap.containsKey(method)) {
+            methodMap.put(method, new MethodElement(method));
+        }
+        return methodMap.get(method);
+    }
+
+    public synchronized ArrayTypeElement getProcessedArrayType(ResolvedJavaType type) {
+        assert type != null;
+        if (!arrayTypeMap.containsKey(type)) {
+            arrayTypeMap.put(type, new ArrayTypeElement(type));
+        }
+        return arrayTypeMap.get(type);
+    }
+
+    public synchronized Element getSinkElement(Node node, Node sourceNode) {
+        if (!sinkMap.containsKey(node)) {
+            Element resultElement = Element.BLACK_HOLE;
+            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(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 || node instanceof InstanceOfNode) {
+                    // OK.
+                } else {
+                    System.out.println("Unknown sink - black hole? " + node);
+                }
+            }
+
+            sinkMap.put(node, resultElement);
+        }
+
+        if (node instanceof StoreIndexedNode) {
+            StoreIndexedNode storeIndexedNode = (StoreIndexedNode) node;
+            if (storeIndexedNode.value() != sourceNode) {
+                return Element.BLACK_HOLE;
+            }
+        }
+
+        if (node instanceof StoreFieldNode) {
+            StoreFieldNode storeFieldNode = (StoreFieldNode) node;
+            if (storeFieldNode.value() != sourceNode) {
+                return Element.BLACK_HOLE;
+            }
+        }
+        return sinkMap.get(node);
+    }
+
+    public synchronized void registerSourceCallTargetNode(MethodCallTargetNode methodCallTargetNode) {
+        InvokeElement invokeElement = new InvokeElement(methodCallTargetNode);
+        sinkMap.put(methodCallTargetNode, invokeElement);
+        invokeElement.expandStaticMethod(this);
+    }
+
+    public synchronized void registerSourceNode(Node node) {
+        Element resultElement = null;
+        if (node instanceof LoadFieldNode) {
+            LoadFieldNode loadFieldNode = (LoadFieldNode) node;
+            resultElement = getProcessedField(loadFieldNode.field());
+        } else if (node instanceof LoadIndexedNode) {
+            LoadIndexedNode loadIndexedNode = (LoadIndexedNode) node;
+            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) {
+                ResolvedJavaMethod method = ((StructuredGraph) localNode.graph()).method();
+                resultElement = getProcessedMethod(method).getParameter(localNode.index());
+                System.out.println("resultElement = " + resultElement + " index= " + localNode.index() + ", node=" + node);
+            }
+        }
+
+        if (resultElement != null) {
+            resultElement.postAddUsage(this, node);
+        }
+    }
+
+    public synchronized void postOperation(UniverseExpansionOp operation) {
+        System.out.println("posting operation " + operation);
+        executor.execute(operation);
+        postedOperationCount++;
+    }
+
+    public MetaAccessProvider getMetaAccess() {
+        return metaAccessProvider;
+    }
+
+    public void finish() {
+        while (true) {
+            try {
+                Thread.sleep(10);
+                boolean terminated;
+                int oldPostedOperationCount;
+                synchronized (this) {
+                    terminated = (executor.getCompletedTaskCount() == postedOperationCount);
+                    oldPostedOperationCount = postedOperationCount;
+                }
+
+                if (terminated) {
+                    checkObjectGraph();
+                    synchronized (this) {
+                        if (postedOperationCount == oldPostedOperationCount) {
+                            System.out.printf("Big bang simulation completed in %d operations.\n", postedOperationCount);
+                            executor.shutdown();
+                            break;
+                        }
+                    }
+                }
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    private void checkObjectGraph() {
+        List<FieldElement> originalRoots = new ArrayList<>();
+        synchronized (this) {
+            for (FieldElement field : fieldMap.values()) {
+                if (field.isStatic()) {
+                    originalRoots.add(field);
+                }
+            }
+        }
+
+        Map<Object, Boolean> scannedObjects = new IdentityHashMap<>();
+        for (FieldElement field : originalRoots) {
+            assert field.isStatic();
+            if (field.getUsageCount() > 0 && field.getJavaField().kind() == Kind.Object) {
+                Object value = field.getJavaField().getValue(null).asObject();
+                System.out.printf("Root field %s: %s\n", field, value);
+                scanField(scannedObjects, field, value);
+            }
+        }
+    }
+
+    private void scanField(Map<Object, Boolean> scannedObjects, FieldElement field, Object value) {
+        if (value != null && field.getUsageCount() > 0) {
+            field.registerNewValue(this, value);
+            scan(scannedObjects, value);
+        }
+    }
+
+    private void scan(Map<Object, Boolean> scannedObjects, Object value) {
+        assert value != null;
+        if (scannedObjects.containsKey(value)) {
+            return;
+        }
+
+        scannedObjects.put(value, Boolean.TRUE);
+        ResolvedJavaType type = getMetaAccess().getResolvedJavaType(value.getClass());
+        scan(scannedObjects, value, type);
+    }
+
+    private void scan(Map<Object, Boolean> scannedObjects, Object value, ResolvedJavaType type) {
+        if (type.superType() != null) {
+            scan(scannedObjects, value, type.superType());
+        }
+
+        ResolvedJavaField[] declaredFields = type.declaredFields();
+        for (ResolvedJavaField field : declaredFields) {
+            if (field.kind() == Kind.Object) {
+                FieldElement fieldElement = getProcessedField(field);
+                Object fieldValue = field.getValue(Constant.forObject(value)).asObject();
+                scanField(scannedObjects, fieldElement, fieldValue);
+            }
+        }
+
+    }
+
+    public synchronized int[] printState() {
+
+        int nativeMethodCount = 0;
+        for (MethodElement methodElement : methodMap.values()) {
+            if (methodElement.hasGraph()) {
+                if (Modifier.isNative(methodElement.getResolvedJavaMethod().accessFlags())) {
+                    System.out.println("Included native method: " + methodElement.getResolvedJavaMethod());
+                    nativeMethodCount++;
+                }
+            }
+        }
+
+        int methodCount = 0;
+        for (MethodElement methodElement : methodMap.values()) {
+            if (methodElement.hasGraph()) {
+                if (!Modifier.isNative(methodElement.getResolvedJavaMethod().accessFlags())) {
+                    System.out.println("Included method: " + methodElement.getResolvedJavaMethod());
+                    methodCount++;
+                }
+            }
+        }
+
+        Set<ResolvedJavaType> includedTypes = new HashSet<>();
+        int fieldCount = 0;
+        for (FieldElement fieldElement : fieldMap.values()) {
+            if (fieldElement.getUsageCount() > 0) {
+                System.out.print("Included field: " + fieldElement.getJavaField() + " / ");
+                fieldElement.printSeenTypes();
+                System.out.println();
+                fieldCount++;
+                includedTypes.add(fieldElement.getJavaField().holder());
+            }
+        }
+
+        for (ResolvedJavaType type : includedTypes) {
+            System.out.println("Included type: " + type);
+        }
+
+        System.out.println("Number of included native methods: " + nativeMethodCount);
+        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()};
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageClassLoader.java	Mon Jun 18 10:07:33 2012 +0200
@@ -0,0 +1,74 @@
+/*
+ * 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.io.*;
+
+public class BootImageClassLoader extends ClassLoader {
+
+    @Override
+    protected java.lang.Class< ? > loadClass(String name, boolean resolve) throws ClassNotFoundException {
+        synchronized (getClassLoadingLock(name)) {
+            Class< ? > result = findLoadedClass(name);
+            if (result == null) {
+                result = super.loadClass(name, resolve);
+                assert result.getName().equals(name);
+                return duplicate(result);
+            }
+            return result;
+        }
+    }
+
+    private Class< ? > duplicate(Class< ? > result) {
+        // This is a class in the bootclasspath => share.
+        if (result.getClassLoader() == null) {
+            return result;
+        }
+
+        // Duplicate class definition.
+        InputStream inputStream = result.getClassLoader().getResourceAsStream(result.getName().replace('.', '/').concat(".class"));
+        try {
+            byte[] byteCodes = new byte[inputStream.available()];
+            inputStream.read(byteCodes);
+            return this.defineClass(result.getName(), byteCodes, 0, byteCodes.length);
+        } catch (IOException e) {
+            throw new RuntimeException("Could not access class bytes for " + result.getName());
+        }
+    }
+
+    public Class< ? > convert(Class< ? > clazz) {
+        synchronized (getClassLoadingLock(clazz.getCanonicalName())) {
+            // This class has this class loader => no conversion necessary.
+            if (clazz.getClassLoader() == this) {
+                return clazz;
+            }
+
+            Class< ? > thisClazz = findLoadedClass(clazz.getName());
+            if (thisClazz != null) {
+                return thisClazz;
+            }
+
+            return duplicate(clazz);
+        }
+    }
+}
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageGenerator.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageGenerator.java	Mon Jun 18 10:07:33 2012 +0200
@@ -22,7 +22,39 @@
  */
 package com.oracle.graal.boot;
 
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.boot.meta.*;
+
 
 public class BootImageGenerator {
 
+    private final BootImageClassLoader classLoader = new BootImageClassLoader();
+    private final MetaAccessProvider metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class);
+    private final BigBang bigbang = new BigBang(metaAccess);
+
+    public void addEntryMethod(Class<?> clazz, String name, Class<?> ... parameterTypes) {
+        Class<?> convertedClass = classLoader.convert(clazz);
+        Method method;
+        try {
+            method = convertedClass.getDeclaredMethod(name, parameterTypes);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new RuntimeException("Could not find method " + name + " with parameter types " + parameterTypes + " in class " + convertedClass.getCanonicalName());
+        }
+        System.out.printf("Adding method %s.%s to the boot image\n", method.getDeclaringClass().getName(), method.getName());
+        addEntryMethod(metaAccess.getResolvedJavaMethod(method));
+    }
+
+
+    private void addEntryMethod(ResolvedJavaMethod javaMethod) {
+        MethodElement methodElement = bigbang.getProcessedMethod(javaMethod);
+        methodElement.postParseGraph(bigbang);
+        bigbang.finish();
+    }
+
+    public BigBang getBigBang() {
+        return bigbang;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/UniverseExpansionOp.java	Mon Jun 18 10:07:33 2012 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+
+public abstract class UniverseExpansionOp implements Runnable {
+
+    public void post(BigBang store) {
+        store.postOperation(this);
+    }
+
+    @Override
+    public void run() {
+        expand();
+    }
+
+    protected abstract void expand();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ArrayTypeElement.java	Mon Jun 18 10:07:33 2012 +0200
@@ -0,0 +1,69 @@
+/*
+ * 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.*;
+import com.oracle.graal.nodes.java.*;
+
+
+public class ArrayTypeElement extends Element {
+
+    private ResolvedJavaType javaType;
+
+    public ArrayTypeElement(ResolvedJavaType javaType) {
+        super(javaType.componentType());
+        this.javaType = javaType;
+    }
+
+    @Override
+    public String 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	Mon Jun 18 10:07:33 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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/Element.java	Mon Jun 18 10:07:33 2012 +0200
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2011, 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.*;
+
+
+public class Element {
+
+    public static final Element BLACK_HOLE = new Element(null);
+
+    protected List<Node> usages = new ArrayList<>(4);
+    protected Set<ResolvedJavaType> seenTypes = new HashSet<>();
+    private ResolvedJavaType declaredType;
+
+    protected Element(ResolvedJavaType declaredType) {
+        this.declaredType = declaredType;
+    }
+
+    public void postUnionTypes(final BigBang bb, final Node sourceNode, final Set<ResolvedJavaType> newSeenTypes) {
+        new UniverseExpansionOp() {
+            @Override
+            protected void expand() {
+                unionTypes(bb, sourceNode, newSeenTypes);
+            }
+
+            @Override
+            public String toString() {
+                return String.format("Add new seen types %s from source node %s to element %s", newSeenTypes, sourceNode, Element.this);
+            }
+        }.post(bb);
+    }
+
+    public void postAddUsage(final BigBang bb, final Node usage) {
+        new UniverseExpansionOp() {
+            @Override
+            protected void expand() {
+                addUsage(bb, usage);
+            }
+
+            @Override
+            public String toString() {
+                return String.format("Add usage %s to element %s", usage, Element.this);
+            }
+        }.post(bb);
+    }
+
+    protected synchronized void unionTypes(BigBang bb, @SuppressWarnings("unused") Node sourceNode, Set<ResolvedJavaType> newSeenTypes) {
+        if (!seenTypes.containsAll(newSeenTypes)) {
+            if (declaredType != null) {
+                for (ResolvedJavaType seenType : newSeenTypes) {
+                    if (!seenType.isSubtypeOf(declaredType)) {
+                        System.out.println("Wrong type found " + seenType + " where declared type of element " + this + " is " + declaredType);
+                        System.exit(-1);
+                    }
+                }
+            }
+            seenTypes.addAll(newSeenTypes);
+            propagateTypes(bb, newSeenTypes);
+        }
+    }
+
+    protected synchronized void propagateTypes(BigBang bb, Set<ResolvedJavaType> newSeenTypes) {
+        for (Node n : usages) {
+            propagateTypes(bb, n, newSeenTypes);
+        }
+    }
+
+    public synchronized int getUsageCount() {
+        return usages.size();
+    }
+
+    protected synchronized void addUsage(BigBang bb, Node usage) {
+        if (!usages.contains(usage)) {
+            usages.add(usage);
+            propagateTypes(bb, usage, seenTypes);
+        }
+    }
+
+    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) {
+                    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() + " ");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/FieldElement.java	Mon Jun 18 10:07:33 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.meta;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.boot.*;
+
+
+public class FieldElement extends Element {
+
+    protected ResolvedJavaField javaField;
+
+    public FieldElement(ResolvedJavaField javaField) {
+        super(javaField.type().resolve(javaField.holder()));
+        this.javaField = javaField;
+    }
+
+    public boolean isStatic() {
+        return Modifier.isStatic(javaField.accessFlags());
+    }
+
+    public ResolvedJavaField getJavaField() {
+        return javaField;
+    }
+
+    @Override
+    public String toString() {
+        return "Field[" + javaField + "]";
+    }
+
+    public synchronized void registerNewValue(BigBang bb, Object value) {
+        if (value != null) {
+            Class<?> clazz = value.getClass();
+            ResolvedJavaType resolvedType = bb.getMetaAccess().getResolvedJavaType(clazz);
+            if (seenTypes.add(resolvedType)) {
+                Set<ResolvedJavaType> newSeenTypes = new HashSet<>();
+                newSeenTypes.add(resolvedType);
+                super.propagateTypes(bb, newSeenTypes);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/InvokeElement.java	Mon Jun 18 10:07:33 2012 +0200
@@ -0,0 +1,117 @@
+/*
+ * 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.*;
+import com.oracle.graal.nodes.java.*;
+
+
+public class InvokeElement extends Element {
+
+    private MethodCallTargetNode methodCallTarget;
+    private Set<ResolvedJavaMethod> concreteTargets = new HashSet<>();
+    private Set<ResolvedJavaType>[] parameterTypes;
+
+    @SuppressWarnings("unchecked")
+    public InvokeElement(MethodCallTargetNode methodCallTarget) {
+        super(methodCallTarget.isStatic() ? null : methodCallTarget.targetMethod().holder());
+        this.methodCallTarget = methodCallTarget;
+        parameterTypes = new Set[methodCallTarget.arguments().size()];
+    }
+
+    @Override
+    protected synchronized void unionTypes(BigBang bb, Node sourceNode, Set<ResolvedJavaType> newSeenTypes) {
+
+        System.out.println("union invoke element " + this + " new types = " + newSeenTypes + " sourceNode= " + sourceNode);
+        int index = 0;
+        for (Node arg : methodCallTarget.arguments()) {
+            if (arg == sourceNode) {
+                System.out.println("source node " + sourceNode + " is at index " + index + " declaredType=" + ((ValueNode) sourceNode).stamp().declaredType());
+                unionTypes(bb, sourceNode, newSeenTypes, index);
+            }
+            ++index;
+        }
+    }
+
+    @Override
+    public String toString() {
+        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());
+                    }
+                    if (!concreteTargets.contains(method)) {
+                        concreteTargets.add(method);
+                        // New concrete method.
+                        MethodElement processedMethod = bb.getProcessedMethod(method);
+                        processedMethod.postParseGraph(bb);
+                        // Propagate types that were previously found for the parameters.
+                        for (int i = 0; i < parameterTypes.length; ++i) {
+                            if (parameterTypes[i] != null) {
+                                HashSet<ResolvedJavaType> newSeenTypesTemp = new HashSet<>(parameterTypes[i]);
+                                bb.getProcessedMethod(method).getParameter(i).postUnionTypes(bb, null, newSeenTypesTemp);
+                            }
+                        }
+                    }
+
+                    // Register new type for receiver.
+                    HashSet<ResolvedJavaType> newSeenTypesTemp = new HashSet<>();
+                    newSeenTypesTemp.add(type);
+                    bb.getProcessedMethod(method).getParameter(index).postUnionTypes(bb, null, newSeenTypesTemp);
+                }
+            }
+        } else {
+            if (parameterTypes[index] == null) {
+                parameterTypes[index] = new HashSet<>();
+            }
+            if (parameterTypes[index].addAll(newSeenTypes)) {
+                for (ResolvedJavaMethod method : concreteTargets) {
+                    HashSet<ResolvedJavaType> newSeenTypesTemp = new HashSet<>(newSeenTypes);
+                    bb.getProcessedMethod(method).getParameter(index).postUnionTypes(bb, null, newSeenTypesTemp);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/MethodElement.java	Mon Jun 18 10:07:33 2012 +0200
@@ -0,0 +1,130 @@
+/*
+ * 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.lang.reflect.*;
+import java.util.*;
+
+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.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+
+
+public class MethodElement extends Element {
+
+    private ParameterElement[] parameters;
+    private Graph graph;
+    private ResolvedJavaMethod resolvedJavaMethod;
+
+    public MethodElement(ResolvedJavaMethod javaMethod) {
+        super(javaMethod.signature().returnType(javaMethod.holder()).resolve(javaMethod.holder()));
+        assert javaMethod != null;
+        this.resolvedJavaMethod = javaMethod;
+        int parameterCount = resolvedJavaMethod.signature().argumentCount(!Modifier.isStatic(resolvedJavaMethod.accessFlags()));
+        parameters = new ParameterElement[parameterCount];
+        for (int i = 0; i < parameters.length; ++i) {
+            parameters[i] = new ParameterElement(resolvedJavaMethod, i);
+        }
+    }
+
+    public ParameterElement getParameter(int index) {
+        return parameters[index];
+    }
+
+    public synchronized boolean hasGraph() {
+        return graph != null;
+    }
+
+    public void postParseGraph(final BigBang bb) {
+        synchronized (this) {
+            if (graph != null) {
+                return;
+            }
+        }
+        new UniverseExpansionOp() {
+            @Override
+            protected void expand() {
+                parseGraph(bb);
+            }
+
+            @Override
+            public String toString() {
+                return String.format("Parsing method %s", resolvedJavaMethod);
+            }
+        }.post(bb);
+    }
+
+    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;
+        }
+
+        if (Modifier.isNative(resolvedJavaMethod.accessFlags())) {
+            System.out.println("NATIVE METHOD " + resolvedJavaMethod);
+            return;
+        }
+
+        System.out.println("parsing graph " + resolvedJavaMethod + ", locals=" + resolvedJavaMethod.maxLocals());
+        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);
+        }
+
+        for (Node node : newGraph.getNodes()) {
+            bb.registerSourceNode(node);
+        }
+
+        for (NewInstanceNode newInstance : newGraph.getNodes(NewInstanceNode.class)) {
+            Set<ResolvedJavaType> types = new HashSet<>();
+            types.add(newInstance.instanceClass());
+            System.out.println("propagate new instance " + newInstance + ", " + newInstance.instanceClass());
+            for (Node use : newInstance.usages()) {
+                Element element = bb.getSinkElement(use, newInstance);
+                assert element != null;
+                if (element != BLACK_HOLE) {
+                    element.postUnionTypes(bb, newInstance, types);
+                }
+            }
+        }
+    }
+
+    public ResolvedJavaMethod getResolvedJavaMethod() {
+        return resolvedJavaMethod;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ParameterElement.java	Mon Jun 18 10:07:33 2012 +0200
@@ -0,0 +1,57 @@
+/*
+ * 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.lang.reflect.*;
+
+import com.oracle.graal.api.meta.*;
+
+
+public class ParameterElement extends Element {
+
+    private int index;
+    private ResolvedJavaMethod method;
+
+    public ParameterElement(ResolvedJavaMethod method, int index) {
+        super(calculateDeclaredType(method, index));
+        this.method = method;
+        this.index = index;
+    }
+
+    private static ResolvedJavaType calculateDeclaredType(ResolvedJavaMethod m, int i) {
+        if (Modifier.isStatic(m.accessFlags())) {
+            return m.signature().argumentTypeAt(i, m.holder()).resolve(m.holder());
+        } else {
+            if (i == 0) {
+                return m.holder();
+            }
+            return m.signature().argumentTypeAt(i - 1, m.holder()).resolve(m.holder());
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "[Parameter, index= " + index + " of method " + method + "]";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/PhiElement.java	Mon Jun 18 10:07:33 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 PhiElement extends Element {
+
+    private PhiNode phi;
+
+    public PhiElement(PhiNode phi) {
+        super(null);
+        this.phi = phi;
+        usages.add(phi);
+    }
+
+    @Override
+    public String 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	Mon Jun 18 10:07:33 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;
+    }
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Mon Jun 18 10:07:33 2012 +0200
@@ -261,7 +261,7 @@
      * Only instructions in methods whose fully qualified name contains this option will be HIR lowered.
      */
     public static String HIRLowerCheckcast = "";
-    public static String HIRLowerNewInstance = "NewInstanceTest";
+    public static String HIRLowerNewInstance = "NewInstanceTest.new";
 
     /**
      * The profiling info cache directory.
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java	Mon Jun 18 10:07:33 2012 +0200
@@ -138,6 +138,9 @@
         }
 
         public void processWrite(WriteNode writeNode) {
+            if (writeNode.location().locationIdentity() == LocationNode.ANY_LOCATION) {
+                map.clear();
+            }
             map.put(writeNode.location().locationIdentity(), writeNode);
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Jun 18 10:07:33 2012 +0200
@@ -204,7 +204,7 @@
     @SuppressWarnings("unchecked")
     @Override
     public <T> T getCapability(Class<T> clazz) {
-        if (clazz == ExtendedRiRuntime.class) {
+        if (clazz == ExtendedRiRuntime.class || clazz == MetaAccessProvider.class) {
             return (T) getRuntime();
         }
         if (clazz == GraalCompiler.class) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Mon Jun 18 10:07:33 2012 +0200
@@ -37,7 +37,7 @@
     // os information, register layout, code generation, ...
     public boolean windowsOs;
     public int codeEntryAlignment;
-    public boolean verifyPointers;
+    public boolean verifyOops;
     public boolean useFastLocking;
     public boolean useFastNewObjectArray;
     public boolean useFastNewTypeArray;
@@ -103,7 +103,7 @@
     public long monitorExitStub;
     public long fastMonitorEnterStub;
     public long fastMonitorExitStub;
-    public long verifyPointerStub;
+    public long verifyOopStub;
 
     public void check() {
         assert vmPageSize >= 16;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Mon Jun 18 10:07:33 2012 +0200
@@ -66,8 +66,7 @@
             if (constant == null) {
                 if (holder.isInitialized() && holder.toJava() != System.class) {
                     if (Modifier.isFinal(accessFlags()) || assumeStaticFieldsFinal(holder.toJava())) {
-                        Constant encoding = holder.getEncoding(Representation.StaticFields);
-                        constant = this.kind().readUnsafeConstant(encoding.asObject(), offset);
+                        constant = getValue(receiver);
                     }
                 }
             }
@@ -76,12 +75,27 @@
             assert !Modifier.isStatic(accessFlags);
             // TODO (chaeubl) HotSpot does not trust final non-static fields (see ciField.cpp)
             if (Modifier.isFinal(accessFlags())) {
-                return this.kind().readUnsafeConstant(receiver.asObject(), offset);
+                return getValue(receiver);
             }
         }
         return null;
     }
 
+    @Override
+    public Constant getValue(Constant receiver) {
+        if (receiver == null) {
+            assert Modifier.isStatic(accessFlags);
+            if (holder.isInitialized()) {
+                Constant encoding = holder.getEncoding(Representation.StaticFields);
+                return this.kind().readUnsafeConstant(encoding.asObject(), offset);
+            }
+            return null;
+        } else {
+            assert !Modifier.isStatic(accessFlags);
+            return this.kind().readUnsafeConstant(receiver.asObject(), offset);
+        }
+    }
+
     private static boolean assumeStaticFieldsFinal(Class< ? > clazz) {
         return clazz == GraalOptions.class;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java	Mon Jun 18 10:07:33 2012 +0200
@@ -121,6 +121,7 @@
             case StaticFields:
                 return Constant.forObject(javaMirror);
             default:
+                assert false : "Should not reach here.";
                 return null;
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Mon Jun 18 10:07:33 2012 +0200
@@ -48,9 +48,9 @@
     @Override
     public void generate(LIRGenerator gen) {
         Variable result = gen.newVariable(Kind.Object);
-        gen.emitMove(gen.operand(hub), AMD64.rdx.asValue());
+        gen.emitMove(gen.operand(hub), AMD64.rdx.asValue(Kind.Object));
         LIRDebugInfo info = gen.state();
-        AMD64NewInstanceStubCallOp op = new AMD64NewInstanceStubCallOp(result, AMD64.rdx.asValue(), info);
+        AMD64NewInstanceStubCallOp op = new AMD64NewInstanceStubCallOp(result, AMD64.rdx.asValue(Kind.Object), info);
         gen.append(op);
         gen.setResult(this, result);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Mon Jun 18 10:07:33 2012 +0200
@@ -0,0 +1,58 @@
+/*
+ * 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.hotspot.nodes;
+
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.hotspot.target.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Node implementing a call to HotSpot's object pointer verification stub.
+ *
+ * @see AMD64VerifyOopStubCallOp
+ */
+public class VerifyOopStubCall extends FixedWithNextNode implements LIRGenLowerable {
+
+    @Input private final ValueNode object;
+
+    public VerifyOopStubCall(ValueNode object) {
+        super(StampFactory.objectNonNull());
+        this.object = object;
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        LIRDebugInfo info = gen.state();
+        AMD64VerifyOopStubCallOp op = new AMD64VerifyOopStubCallOp(gen.operand(object), info);
+        gen.append(op);
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static Object call(Object object) {
+        throw new UnsupportedOperationException();
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java	Mon Jun 18 10:07:33 2012 +0200
@@ -72,7 +72,7 @@
                     Log.print(logType);
                     Log.println(" - uninit alloc");
                 }
-                return NewInstanceStubCall.call(hub);
+                return verifyOop(NewInstanceStubCall.call(hub));
             }
         }
 
@@ -90,7 +90,7 @@
                     Log.print(" - fast alloc at ");
                     Log.printlnAddress(instance);
                 }
-                return instance;
+                return verifyOop(instance);
             }
         }
 
@@ -98,7 +98,14 @@
             Log.print(logType);
             Log.println(" - slow alloc");
         }
-        return NewInstanceStubCall.call(hub);
+        return verifyOop(NewInstanceStubCall.call(hub));
+    }
+
+    private static Object verifyOop(Object object) {
+        if (verifyOops()) {
+            VerifyOopStubCall.call(object);
+        }
+        return object;
     }
 
     private static Word asWord(Object object) {
@@ -123,6 +130,11 @@
     }
 
     @Fold
+    private static boolean verifyOops() {
+        return HotSpotGraalRuntime.getInstance().getConfig().verifyOops;
+    }
+
+    @Fold
     private static int klassStateOffset() {
         return HotSpotGraalRuntime.getInstance().getConfig().klassStateOffset;
     }
@@ -196,6 +208,7 @@
             SnippetTemplate template = cache.get(key);
             Debug.log("Lowering newInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, arguments);
             //System.out.printf("Lowering newInstance in %s: node=%s, template=%s, arguments=%s%n", graph, newInstanceNode, template, arguments);
+            //DebugScope.getConfig().addToContext(graph.method());
             template.instantiate(runtime, newInstanceNode, newInstanceNode, arguments);
             new DeadCodeEliminationPhase().apply(graph);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java	Mon Jun 18 10:07:33 2012 +0200
@@ -40,7 +40,7 @@
  */
 public class AMD64NewInstanceStubCallOp extends AMD64LIRInstruction {
     public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRDebugInfo info) {
-        super("NEW_INSTANCE", new Value[] {result}, info, new Value[] {hub}, NO_OPERANDS, NO_OPERANDS);
+        super("NEW_INSTANCE", new Value[] {result}, info, new Value[] {hub}, NO_OPERANDS, new Value[]{AMD64.rax.asValue(Kind.Object)});
     }
 
     @Override
@@ -63,6 +63,8 @@
             return EnumSet.of(OperandFlag.Register);
         } else if (mode == OperandMode.Output) {
             return EnumSet.of(OperandFlag.Register);
+        } else if (mode == OperandMode.Temp) {
+            return EnumSet.of(OperandFlag.Register);
         }
         throw GraalInternalError.shouldNotReachHere();
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java	Mon Jun 18 10:07:33 2012 +0200
@@ -0,0 +1,67 @@
+/*
+ * 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.hotspot.target;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+
+/**
+ * A call to HotSpot's object pointer verification stub.
+ */
+public class AMD64VerifyOopStubCallOp extends AMD64LIRInstruction {
+    public AMD64VerifyOopStubCallOp(Value object, LIRDebugInfo info) {
+        super("VERIFY_OOP", LIRInstruction.NO_OPERANDS, info, new Value[] {object}, NO_OPERANDS, NO_OPERANDS);
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        Register object = asRegister(input(0));
+        // r13: (in) object
+        if (object != AMD64.r13) {
+            masm.push(AMD64.r13);
+            masm.movl(AMD64.r13, object);
+        }
+        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, info);
+        if (object != AMD64.r13) {
+            masm.pop(AMD64.r13);
+        }
+    }
+
+    @Override
+    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+        if (mode == OperandMode.Input) {
+            return EnumSet.of(OperandFlag.Register);
+        }
+        throw GraalInternalError.shouldNotReachHere();
+    }
+}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Jun 18 10:07:33 2012 +0200
@@ -68,7 +68,7 @@
 
     private StructuredGraph currentGraph;
 
-    private final CodeCacheProvider runtime;
+    private final MetaAccessProvider runtime;
     private ConstantPool constantPool;
     private ResolvedJavaMethod method;
     private ProfilingInfo profilingInfo;
@@ -104,11 +104,12 @@
 
     private Block[] loopHeaders;
 
-    public GraphBuilderPhase(CodeCacheProvider runtime, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) {
+    public GraphBuilderPhase(MetaAccessProvider runtime, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) {
         this.graphBuilderConfig = graphBuilderConfig;
         this.optimisticOpts = optimisticOpts;
         this.runtime = runtime;
         this.log = GraalOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null;
+        assert runtime != null;
     }
 
     @Override
@@ -1097,6 +1098,7 @@
     }
 
     private ConstantNode appendConstant(Constant constant) {
+        assert constant != null;
         return ConstantNode.forConstant(constant, runtime, currentGraph);
     }
 
@@ -1394,10 +1396,16 @@
         ConstantNode typeInstruction = genTypeOrDeopt(JavaType.Representation.ObjectHub, catchType, initialized);
         if (typeInstruction != null) {
             Block nextBlock = block.successors.size() == 1 ? unwindBlock(block.deoptBci) : block.successors.get(1);
+            ValueNode exception = frameState.stackAt(0);
+            CheckCastNode checkCast = currentGraph.add(new CheckCastNode(typeInstruction, (ResolvedJavaType) catchType, exception));
+            frameState.apop();
+            frameState.push(Kind.Object, checkCast);
             FixedNode catchSuccessor = createTarget(block.successors.get(0), frameState);
+            frameState.apop();
+            frameState.push(Kind.Object, exception);
             FixedNode nextDispatch = createTarget(nextBlock, frameState);
-            ValueNode exception = frameState.stackAt(0);
-            IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new InstanceOfNode(typeInstruction, (ResolvedJavaType) catchType, exception)), catchSuccessor, nextDispatch, 0.5));
+            checkCast.setNext(catchSuccessor);
+            IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new InstanceOfNode(typeInstruction, (ResolvedJavaType) catchType, exception)), checkCast, nextDispatch, 0.5));
             append(ifNode);
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ReassociateConstants.java	Mon Jun 18 10:07:33 2012 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, 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.jtt.optimize;
+
+import org.junit.*;
+
+
+public class ReassociateConstants {
+    public static int rnd = (int) (Math.random() * 100);
+    @Test
+    public void run0() throws Throwable {
+        Assert.assertEquals(rnd + 3, 1 + (rnd + 2));
+        Assert.assertEquals(rnd + 3, (rnd + 2) + 1);
+        Assert.assertEquals(rnd + 3, 1 + (2 + rnd));
+        Assert.assertEquals(rnd + 3, (2 + rnd) + 1);
+
+        Assert.assertEquals(-1 - rnd, 1 - (rnd + 2));
+        Assert.assertEquals(rnd + 1, (rnd + 2) - 1);
+        Assert.assertEquals(-1 - rnd, 1 - (2 + rnd));
+        Assert.assertEquals(rnd + 1, (2 + rnd) - 1);
+
+        Assert.assertEquals(rnd - 1, 1 + (rnd - 2));
+        Assert.assertEquals(rnd - 1, (rnd - 2) + 1);
+        Assert.assertEquals(-rnd + 3, 1 + (2 - rnd));
+        Assert.assertEquals(-rnd + 3, (2 - rnd) + 1);
+
+        Assert.assertEquals(-rnd + 3, 1 - (rnd - 2));
+        Assert.assertEquals(rnd - 3, (rnd - 2) - 1);
+        Assert.assertEquals(rnd + -1, 1 - (2 - rnd));
+        Assert.assertEquals(-rnd + 1, (2 - rnd) - 1);
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Mon Jun 18 10:07:33 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
@@ -47,7 +46,7 @@
      * Constructs a new ConstantNode representing the specified constant.
      * @param value the constant
      */
-    protected ConstantNode(Constant value, CodeCacheProvider runtime) {
+    protected ConstantNode(Constant value, MetaAccessProvider runtime) {
         super(StampFactory.forConstant(value, runtime));
         this.value = value;
     }
@@ -65,7 +64,7 @@
         return usages().filter(NodePredicates.isNotA(FrameState.class)).isEmpty();
     }
 
-    public static ConstantNode forConstant(Constant constant, CodeCacheProvider runtime, Graph graph) {
+    public static ConstantNode forConstant(Constant constant, MetaAccessProvider runtime, Graph graph) {
         if (constant.kind == Kind.Object) {
             return graph.unique(new ConstantNode(constant, runtime));
         } else {
@@ -169,7 +168,7 @@
      * @param graph
      * @return a node representing the object
      */
-    public static ConstantNode forObject(Object o, CodeCacheProvider runtime, Graph graph) {
+    public static ConstantNode forObject(Object o, MetaAccessProvider runtime, Graph graph) {
         return graph.unique(new ConstantNode(Constant.forObject(o), runtime));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Mon Jun 18 10:07:33 2012 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.type.GenericStamp.*;
 import com.oracle.graal.nodes.util.*;
@@ -89,6 +90,17 @@
         return this instanceof ConstantNode;
     }
 
+    private static final NodePredicate IS_CONSTANT = new NodePredicate() {
+        @Override
+        public boolean apply(Node n) {
+            return n instanceof ValueNode && ((ValueNode) n).isConstant();
+        }
+    };
+
+    public static NodePredicate isConstantPredicate() {
+        return IS_CONSTANT;
+    }
+
     /**
      * Checks whether this value represents the null constant.
      * @return {@code true} if this value represents the null constant
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java	Mon Jun 18 10:07:33 2012 +0200
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.Node.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.type.*;
 
 /**
  * A value proxy that is inserted in the frame state of a loop exit for any value that is
@@ -49,6 +50,11 @@
         return value;
     }
 
+    @Override
+    public Stamp stamp() {
+        return value.stamp();
+    }
+
     public BeginNode proxyPoint() {
         return proxyPoint;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Mon Jun 18 10:07:33 2012 +0200
@@ -68,6 +68,7 @@
                     return ConstantNode.forLong(0, graph());
                 }
             }
+            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Mon Jun 18 10:07:33 2012 +0200
@@ -23,6 +23,8 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -53,4 +55,135 @@
         this.x = x;
         this.y = y;
     }
+
+    public enum ReassociateMatch {
+        x,
+        y;
+
+        public ValueNode getValue(BinaryNode binary) {
+            switch(this) {
+                case x:
+                    return binary.x();
+                case y:
+                    return binary.y();
+                default: throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+
+        public ValueNode getOtherValue(BinaryNode binary) {
+            switch(this) {
+                case x:
+                    return binary.y();
+                case y:
+                    return binary.x();
+                default: throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    public static boolean canTryReassociate(BinaryNode node) {
+        return node instanceof IntegerAddNode || node instanceof IntegerSubNode || node instanceof IntegerMulNode
+                        || node instanceof AndNode || node instanceof OrNode || node instanceof XorNode;
+    }
+
+    public static ReassociateMatch findReassociate(BinaryNode binary, NodePredicate criterion) {
+        boolean resultX = criterion.apply(binary.x());
+        boolean resultY = criterion.apply(binary.y());
+        if (resultX && !resultY) {
+            return ReassociateMatch.x;
+        }
+        if (!resultX && resultY) {
+            return ReassociateMatch.y;
+        }
+        return null;
+    }
+
+    /* In reassociate, complexity comes from the handling of IntegerSub (non commutative) which can be mixed with IntegerAdd.
+     * if first tries to find m1, m2 which match the criterion :
+     * (a o m2) o m1
+     * (m2 o a) o m1
+     * m1 o (a o m2)
+     * m1 o (m2 o a)
+     * It then produces 4 boolean for the -/+ case
+     *  invertA : should the final expression be like *-a (rather than a+*)
+     *  aSub : should the final expression be like a-* (rather than a+*)
+     *  invertM1 : should the final expression contain -m1
+     *  invertM2 : should the final expression contain -m2
+     */
+    /**
+     * Tries to re-associate values which satisfy the criterion.
+     * For example with a constantness criterion : (a + 2) + 1 => a + (1 + 2)<br>
+     * This method accepts only reassociable operations (see {@linkplain #canTryReassociate(BinaryNode)}) such as +, -, *, &, | and ^
+     */
+    public static BinaryNode reassociate(BinaryNode node, NodePredicate criterion) {
+        assert canTryReassociate(node);
+        ReassociateMatch match1 = findReassociate(node, criterion);
+        if (match1 == null) {
+            return node;
+        }
+        ValueNode otherValue = match1.getOtherValue(node);
+        boolean addSub = false;
+        boolean subAdd = false;
+        if (otherValue.getClass() != node.getClass()) {
+            if (node instanceof IntegerAddNode && otherValue instanceof IntegerSubNode) {
+                addSub = true;
+            } else if (node instanceof IntegerSubNode && otherValue instanceof IntegerAddNode) {
+                subAdd = true;
+            } else {
+                return node;
+            }
+        }
+        BinaryNode other = (BinaryNode) otherValue;
+        ReassociateMatch match2 = findReassociate(other, criterion);
+        if (match2 == null) {
+            return node;
+        }
+        boolean invertA = false;
+        boolean aSub =  false;
+        boolean invertM1 = false;
+        boolean invertM2 = false;
+        if (addSub) {
+            invertM2 = match2 == ReassociateMatch.y;
+            invertA = !invertM2;
+        } else if (subAdd) {
+            invertA = invertM2 = match1 == ReassociateMatch.x;
+            invertM1 = !invertM2;
+        } else if (node instanceof IntegerSubNode && other instanceof IntegerSubNode) {
+            invertA = match1 == ReassociateMatch.x ^ match2 == ReassociateMatch.x;
+            aSub = match1 == ReassociateMatch.y && match2 == ReassociateMatch.y;
+            invertM1 = match1 == ReassociateMatch.y && match2 == ReassociateMatch.x;
+            invertM2 = match1 == ReassociateMatch.x && match2 == ReassociateMatch.x;
+        }
+        assert !(invertM1 && invertM2) && !(invertA && aSub);
+        ValueNode m1 = match1.getValue(node);
+        ValueNode m2 = match2.getValue(other);
+        ValueNode a = match2.getOtherValue(other);
+        if (node instanceof IntegerAddNode || node instanceof IntegerSubNode) {
+            BinaryNode associated;
+            if (invertM1) {
+                associated = IntegerArithmeticNode.sub(m2, m1);
+            } else if (invertM2) {
+                associated = IntegerArithmeticNode.sub(m1, m2);
+            } else {
+                associated = IntegerArithmeticNode.add(m1, m2);
+            }
+            if (invertA) {
+                return IntegerArithmeticNode.sub(associated, a);
+            }
+            if (aSub) {
+                return IntegerArithmeticNode.sub(a, associated);
+            }
+            return IntegerArithmeticNode.add(a, associated);
+        } else if (node instanceof IntegerMulNode) {
+            return IntegerArithmeticNode.mul(a, IntegerAddNode.mul(m1, m2));
+        } else if (node instanceof AndNode) {
+            return LogicNode.and(a, LogicNode.and(m1, m2));
+        } else if (node instanceof OrNode) {
+            return LogicNode.or(a, LogicNode.or(m1, m2));
+        } else if (node instanceof XorNode) {
+            return LogicNode.xor(a, LogicNode.xor(m1, m2));
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Mon Jun 18 10:07:33 2012 +0200
@@ -48,33 +48,27 @@
                 return ConstantNode.forLong(x().asConstant().asLong() + y().asConstant().asLong(), graph());
             }
         } else if (y().isConstant()) {
-            if (kind() == Kind.Int) {
-                int c = y().asConstant().asInt();
-                if (c == 0) {
-                    return x();
-                }
-            } else {
-                assert kind() == Kind.Long;
-                long c = y().asConstant().asLong();
-                if (c == 0) {
-                    return x();
-                }
+            long c = y().asConstant().asLong();
+            if (c == 0) {
+                return x();
             }
             // canonicalize expressions like "(a + 1) + 2"
-            if (x() instanceof IntegerAddNode) {
-                IntegerAddNode other = (IntegerAddNode) x();
-                if (other.y().isConstant()) {
-                    ConstantNode sum;
-                    if (kind() == Kind.Int) {
-                        sum = ConstantNode.forInt(y().asConstant().asInt() + other.y().asConstant().asInt(), graph());
-                    } else {
-                        assert kind() == Kind.Long;
-                        sum = ConstantNode.forLong(y().asConstant().asLong() + other.y().asConstant().asLong(), graph());
-                    }
-                    return graph().unique(new IntegerAddNode(kind(), other.x(), sum));
+            BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
+            if (reassociated != this) {
+                return reassociated;
+            }
+            if (c < 0) {
+                if (kind() == Kind.Int) {
+                    return IntegerArithmeticNode.sub(x(), ConstantNode.forInt((int) -c, graph()));
+                } else {
+                    assert kind() == Kind.Long;
+                    return IntegerArithmeticNode.sub(x(), ConstantNode.forLong(-c, graph()));
                 }
             }
         }
+        if (x() instanceof NegateNode) {
+            return IntegerArithmeticNode.sub(y(), ((NegateNode) x()).x());
+        }
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Mon Jun 18 10:07:33 2012 +0200
@@ -59,19 +59,7 @@
                 return graph().unique(new LeftShiftNode(kind(), x(), ConstantNode.forInt(CodeUtil.log2(c), graph())));
             }
             // canonicalize expressions like "(a * 1) * 2"
-            if (x() instanceof IntegerMulNode) {
-                IntegerMulNode other = (IntegerMulNode) x();
-                if (other.y().isConstant()) {
-                    ConstantNode sum;
-                    if (kind() == Kind.Int) {
-                        sum = ConstantNode.forInt(y().asConstant().asInt() * other.y().asConstant().asInt(), graph());
-                    } else {
-                        assert kind() == Kind.Long;
-                        sum = ConstantNode.forLong(y().asConstant().asLong() * other.y().asConstant().asLong(), graph());
-                    }
-                    return graph().unique(new IntegerMulNode(kind(), other.x(), sum));
-                }
-            }
+            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Mon Jun 18 10:07:33 2012 +0200
@@ -51,17 +51,24 @@
             if (c == 0) {
                 return x();
             }
-            if (kind() == Kind.Int) {
-                return graph().unique(new IntegerAddNode(kind(), x(), ConstantNode.forInt((int) -c, graph())));
-            } else {
-                assert kind() == Kind.Long;
-                return graph().unique(new IntegerAddNode(kind(), x(), ConstantNode.forLong(-c, graph())));
+            BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
+            if (reassociated != this) {
+                return reassociated;
+            }
+            if (c < 0) {
+                if (kind() == Kind.Int) {
+                    return IntegerArithmeticNode.add(x(), ConstantNode.forInt((int) -c, graph()));
+                } else {
+                    assert kind() == Kind.Long;
+                    return IntegerArithmeticNode.add(x(), ConstantNode.forLong(-c, graph()));
+                }
             }
         } else if (x().isConstant()) {
             long c = x().asConstant().asLong();
             if (c == 0) {
                 return graph().unique(new NegateNode(y()));
             }
+           return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LogicNode.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LogicNode.java	Mon Jun 18 10:07:33 2012 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
 /**
@@ -38,4 +39,43 @@
     public LogicNode(Kind kind, ValueNode x, ValueNode y) {
         super(kind, x, y);
     }
+
+    public static LogicNode and(ValueNode v1, ValueNode v2) {
+        assert v1.kind() == v2.kind() && v1.graph() == v2.graph();
+        Graph graph = v1.graph();
+        switch(v1.kind()) {
+            case Int:
+                return graph.unique(new AndNode(Kind.Int, v1, v2));
+            case Long:
+                return graph.unique(new AndNode(Kind.Long, v1, v2));
+            default:
+                throw ValueNodeUtil.shouldNotReachHere();
+        }
+    }
+
+    public static LogicNode or(ValueNode v1, ValueNode v2) {
+        assert v1.kind() == v2.kind() && v1.graph() == v2.graph();
+        Graph graph = v1.graph();
+        switch(v1.kind()) {
+            case Int:
+                return graph.unique(new OrNode(Kind.Int, v1, v2));
+            case Long:
+                return graph.unique(new OrNode(Kind.Long, v1, v2));
+            default:
+                throw ValueNodeUtil.shouldNotReachHere();
+        }
+    }
+
+    public static LogicNode xor(ValueNode v1, ValueNode v2) {
+        assert v1.kind() == v2.kind() && v1.graph() == v2.graph();
+        Graph graph = v1.graph();
+        switch(v1.kind()) {
+            case Int:
+                return graph.unique(new XorNode(Kind.Int, v1, v2));
+            case Long:
+                return graph.unique(new XorNode(Kind.Long, v1, v2));
+            default:
+                throw ValueNodeUtil.shouldNotReachHere();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Mon Jun 18 10:07:33 2012 +0200
@@ -68,6 +68,7 @@
                     return x();
                 }
             }
+            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Mon Jun 18 10:07:33 2012 +0200
@@ -62,6 +62,7 @@
                     return x();
                 }
             }
+            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Mon Jun 18 10:07:33 2012 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.nodes.java;
 
-import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -36,7 +36,7 @@
     /**
      * Constructs a new ExceptionObject instruction.
      */
-    public ExceptionObjectNode(CodeCacheProvider runtime) {
+    public ExceptionObjectNode(MetaAccessProvider runtime) {
         super(StampFactory.declared(runtime.getResolvedJavaType(Throwable.class)));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Fri Jun 15 15:59:43 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Mon Jun 18 10:07:33 2012 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.type.GenericStamp.GenericStampType;
@@ -119,7 +118,7 @@
         }
     }
 
-    public static Stamp forConstant(Constant value, CodeCacheProvider runtime) {
+    public static Stamp forConstant(Constant value, MetaAccessProvider runtime) {
         assert value.kind == Kind.Object;
         if (value.kind == Kind.Object) {
             ResolvedJavaType type = value.isNull() ? null : runtime.getTypeOf(value);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/ReassociateAndCanonicalTest.java	Mon Jun 18 10:07:33 2012 +0200
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2011, 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.tests;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.phases.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+
+public class ReassociateAndCanonicalTest extends GraalCompilerTest {
+    public static int rnd = (int) (Math.random() * 100);
+
+    @Test
+    public void test1() {
+        test("test1Snippet", "ref1Snippet");
+    }
+
+    public static int test1Snippet() {
+        return 1 + (rnd + 2);
+    }
+
+    public static int ref1Snippet() {
+        return rnd + 3;
+    }
+
+    @Test
+    public void test2() {
+        test("test2Snippet", "ref2Snippet");
+    }
+
+    public static int test2Snippet() {
+        return rnd + 3;
+    }
+
+    public static int ref2Snippet() {
+        return (rnd + 2) + 1;
+    }
+
+    @Test
+    public void test3() {
+        test("test3Snippet", "ref3Snippet");
+    }
+
+    public static int test3Snippet() {
+        return rnd + 3;
+    }
+
+    public static int ref3Snippet() {
+        return 1 + (2 + rnd);
+    }
+
+    @Test
+    public void test4() {
+        test("test4Snippet", "ref4Snippet");
+    }
+
+    public static int test4Snippet() {
+        return rnd + 3;
+    }
+
+    public static int ref4Snippet() {
+        return (2 + rnd) + 1;
+    }
+
+    @Test
+    public void test5() {
+        test("test5Snippet", "ref5Snippet");
+    }
+
+    public static int test5Snippet() {
+        return -1 - rnd;
+    }
+
+    public static int ref5Snippet() {
+        return 1 - (rnd + 2);
+    }
+
+    @Test
+    public void test6() {
+        test("test6Snippet", "ref6Snippet");
+    }
+
+    public static int test6Snippet() {
+        return rnd + 1;
+    }
+
+    public static int ref6Snippet() {
+        return (rnd + 2) - 1;
+    }
+
+    @Test
+    public void test7() {
+        test("test7Snippet", "ref7Snippet");
+    }
+
+    public static int test7Snippet() {
+        return -1 - rnd;
+    }
+
+    public static int ref7Snippet() {
+        return 1 - (2 + rnd);
+    }
+
+    @Test
+    public void test8() {
+        test("test8Snippet", "ref8Snippet");
+    }
+
+    public static int test8Snippet() {
+        return rnd + 1;
+    }
+
+    public static int ref8Snippet() {
+        return (2 + rnd) - 1;
+    }
+
+    @Test
+    public void test9() {
+        test("test9Snippet", "ref9Snippet");
+    }
+
+    public static int test9Snippet() {
+        return rnd - 1;
+    }
+
+    public static int ref9Snippet() {
+        return 1 + (rnd - 2);
+    }
+
+    @Test
+    public void test10() {
+        test("test10Snippet", "ref10Snippet");
+    }
+
+    public static int test10Snippet() {
+        return rnd - 1;
+    }
+
+    public static int ref10Snippet() {
+        return (rnd - 2) + 1;
+    }
+
+    @Test
+    public void test11() {
+        test("test11Snippet", "ref11Snippet");
+    }
+
+    public static int test11Snippet() {
+        return -rnd + 3;
+    }
+
+    public static int ref11Snippet() {
+        return 1 + (2 - rnd);
+    }
+
+    @Test
+    public void test12() {
+        test("test12Snippet", "ref12Snippet");
+    }
+
+    public static int test12Snippet() {
+        return -rnd + 3;
+    }
+
+    public static int ref12Snippet() {
+        return (2 - rnd) + 1;
+    }
+
+    @Test
+    public void test13() {
+        test("test13Snippet", "ref13Snippet");
+    }
+
+    public static int test13Snippet() {
+        return -rnd + 3;
+    }
+
+    public static int ref13Snippet() {
+        return 1 - (rnd - 2);
+    }
+
+    @Test
+    public void test14() {
+        test("test14Snippet", "ref14Snippet");
+    }
+
+    public static int test14Snippet() {
+        return rnd - 3;
+    }
+
+    public static int ref14Snippet() {
+        return (rnd - 2) - 1;
+    }
+
+    @Test
+    public void test15() {
+        test("test15Snippet", "ref15Snippet");
+    }
+
+    public static int test15Snippet() {
+        return rnd + -1;
+    }
+
+    public static int ref15Snippet() {
+        return 1 - (2 - rnd);
+    }
+
+    @Test
+    public void test16() {
+        test("test16Snippet", "ref16Snippet");
+    }
+
+    public static int test16Snippet() {
+        return -rnd + 1;
+    }
+
+    public static int ref16Snippet() {
+        return (2 - rnd) - 1;
+    }
+
+    private <T extends Node & Node.IterableNodeType> void test(String test, String ref) {
+        StructuredGraph testGraph = parse(test);
+        new CanonicalizerPhase(null, runtime(), null).apply(testGraph);
+        StructuredGraph refGraph = parse(ref);
+        new CanonicalizerPhase(null, runtime(), null).apply(refGraph);
+        assertEquals(testGraph, refGraph);
+    }
+}
--- a/mx/projects	Fri Jun 15 15:59:43 2012 +0200
+++ b/mx/projects	Mon Jun 18 10:07:33 2012 +0200
@@ -147,7 +147,7 @@
 # graal.boot
 project@com.oracle.graal.boot@subDir=graal
 project@com.oracle.graal.boot@sourceDirs=src
-project@com.oracle.graal.boot@dependencies=com.oracle.graal.compiler
+project@com.oracle.graal.boot@dependencies=com.oracle.graal.java,com.oracle.graal.api
 project@com.oracle.graal.boot@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.boot@javaCompliance=1.7
 
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Fri Jun 15 15:59:43 2012 +0200
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Mon Jun 18 10:07:33 2012 +0200
@@ -1955,8 +1955,8 @@
       break;
     }
 
-    case graal_verify_pointer_id: {
-      __ verify_oop(r13, "graal verify pointer");
+    case graal_verify_oop_id: {
+      __ verify_oop(r13, "graal verify oop");
       __ ret(0);
       break;
     }
--- a/src/share/vm/c1/c1_Runtime1.cpp	Fri Jun 15 15:59:43 2012 +0200
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Mon Jun 18 10:07:33 2012 +0200
@@ -206,7 +206,7 @@
     case handle_exception_nofpu_id:  // Unused on sparc
 #endif
 #ifdef GRAAL
-    case graal_verify_pointer_id:
+    case graal_verify_oop_id:
     case graal_unwind_exception_call_id:
     case graal_slow_subtype_check_id:
     case graal_arithmetic_frem_id:
--- a/src/share/vm/c1/c1_Runtime1.hpp	Fri Jun 15 15:59:43 2012 +0200
+++ b/src/share/vm/c1/c1_Runtime1.hpp	Mon Jun 18 10:07:33 2012 +0200
@@ -76,7 +76,7 @@
   stub(graal_arithmetic_drem)        \
   stub(graal_monitorenter)           \
   stub(graal_monitorexit)            \
-  stub(graal_verify_pointer)         \
+  stub(graal_verify_oop)         \
   stub(graal_set_deopt_info)         \
   stub(graal_create_null_pointer_exception) \
   stub(graal_create_out_of_bounds_exception) \
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Fri Jun 15 15:59:43 2012 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Mon Jun 18 10:07:33 2012 +0200
@@ -781,7 +781,7 @@
 #else
   set_boolean(env, config, "windowsOs", false);
 #endif
-  set_boolean(env, config, "verifyPointers", VerifyOops);
+  set_boolean(env, config, "verifyOops", VerifyOops);
   set_boolean(env, config, "useFastLocking", UseFastLocking);
   set_boolean(env, config, "useFastNewObjectArray", UseFastNewObjectArray);
   set_boolean(env, config, "useFastNewTypeArray", UseFastNewTypeArray);
@@ -823,7 +823,7 @@
 
   set_long(env, config, "debugStub", VmIds::addStub((address)warning));
   set_long(env, config, "instanceofStub", VmIds::addStub(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
-  set_long(env, config, "verifyPointerStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_verify_pointer_id)));
+  set_long(env, config, "verifyOopStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_verify_oop_id)));
   set_long(env, config, "newInstanceStub", VmIds::addStub(Runtime1::entry_for(newInstanceStub)));
   set_long(env, config, "newTypeArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_type_array_id)));
   set_long(env, config, "newObjectArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_object_array_id)));