changeset 5857:7b7881766ed1

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Wed, 18 Jul 2012 10:50:57 -0700
parents a3e7b8320165 (current diff) 0278da961319 (diff)
children 911315a3e642
files graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/CodeInfo.java graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/InstalledCode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotProxy.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetMethod.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/TemplateFlag.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectObjectStoreNode.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinterDumpHandler.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CheckCastTest.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InstanceOfTest.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeTest.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/NewArrayTest.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/NewInstanceTest.java graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/TypeCheckTest.java graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java
diffstat 223 files changed, 8246 insertions(+), 5404 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Thu Jul 05 11:48:30 2012 +0200
+++ b/.hgignore	Wed Jul 18 10:50:57 2012 -0700
@@ -55,3 +55,5 @@
 ^.hgtip
 .DS_Store
 javadoc/
+syntax: glob
+*.bgv
--- a/GRAAL_AUTHORS	Thu Jul 05 11:48:30 2012 +0200
+++ b/GRAAL_AUTHORS	Wed Jul 18 10:50:57 2012 -0700
@@ -1,5 +1,7 @@
 Gilles Duboscq (gdub)
 Peter Hofer
+Alexander Stipsits
+Katrin Strassl
 Christian Humer (chumer)
 Christian Wimmer (cwimmer)
 Doug Simon (dnsimon)
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Address.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Address.java	Wed Jul 18 10:50:57 2012 -0700
@@ -45,7 +45,8 @@
     private final int displacement;
 
     /**
-     * Creates a {@code CiAddress} with given base register, no scaling and no displacement.
+     * Creates an {@link Address} with given base register, no scaling and no displacement.
+     *
      * @param kind the kind of the value being addressed
      * @param base the base register
      */
@@ -54,7 +55,8 @@
     }
 
     /**
-     * Creates a {@code CiAddress} with given base register, no scaling and a given displacement.
+     * Creates an {@link Address} with given base register, no scaling and a given displacement.
+     *
      * @param kind the kind of the value being addressed
      * @param base the base register
      * @param displacement the displacement
@@ -64,8 +66,9 @@
     }
 
     /**
-     * Creates a {@code CiAddress} with given base and index registers, scaling and displacement.
-     * This is the most general constructor..
+     * Creates an {@link Address} with given base and index registers, scaling and displacement.
+     * This is the most general constructor.
+     *
      * @param kind the kind of the value being addressed
      * @param base the base register
      * @param index the index register
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BailoutException.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BailoutException.java	Wed Jul 18 10:50:57 2012 -0700
@@ -25,7 +25,7 @@
 import java.util.*;
 
 /**
- * {@code CiBailout} is thrown when the compiler refuses to compile a method because of problems with the method.
+ * Exception thrown when the compiler refuses to compile a method because of problems with the method.
  * e.g. bytecode wouldn't verify, too big, JSR/ret too complicated, etc. This exception is <i>not</i>
  * meant to indicate problems with the compiler itself.
  */
@@ -34,7 +34,8 @@
     public static final long serialVersionUID = 8974598793458772L;
 
     /**
-     * Create a new {@code CiBailout}.
+     * Creates a new {@link BailoutException}.
+     *
      * @param reason a message indicating the reason
      */
     public BailoutException(String reason) {
@@ -42,7 +43,8 @@
     }
 
     /**
-     * Create a new {@code CiBailout}.
+     * Creates a new {@link BailoutException}.
+     *
      * @param args parameters to the formatter
      */
     public BailoutException(String format, Object... args) {
@@ -50,7 +52,8 @@
     }
 
     /**
-     * Create a new {@code CiBailout} t due to an internal exception being thrown.
+     * Creates a new {@link BailoutException} due to an internal exception being thrown.
+     *
      * @param reason a message indicating the reason
      * @param cause the throwable that was the cause of the bailout
      */
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Wed Jul 18 10:50:57 2012 -0700
@@ -77,14 +77,15 @@
     long getMaxCallTargetOffset(RuntimeCall rtcall);
 
     /**
-     * Adds the given machine code as an implementation of the given method without making it the default implementation.
+     * Adds the given compilation result as an implementation of the given method without making it the default implementation.
+     *
      * @param method a method to which the executable code is begin added
-     * @param code the code to be added
+     * @param compResult the compilation result to be added
      * @param info the object into which details of the installed code will be written.
      *        Ignored if null, otherwise the info is written to index 0 of this array.
      * @return a reference to the compiled and ready-to-run code
      */
-    InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult code, CodeInfo[] info);
+    InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info);
 
     /**
      * Encodes a deoptimization action and a deoptimization reason in an integer value.
@@ -93,14 +94,16 @@
     int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason);
 
     /**
-     * Converts a RiDeoptReason into an integer value.
-     * @return An integer value representing the given RiDeoptReason.
+     * Converts a {@link DeoptimizationReason} into an integer value.
+     *
+     * @return an integer value representing the given {@link DeoptimizationReason}
      */
     int convertDeoptReason(DeoptimizationReason reason);
 
     /**
-     * Converts a RiDeoptAction into an integer value.
-     * @return An integer value representing the given RiDeoptAction.
+     * Converts a {@link DeoptimizationAction} into an integer value.
+     *
+     * @return an integer value representing the given {@link DeoptimizationAction}
      */
     int convertDeoptAction(DeoptimizationAction action);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeInfo.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,48 @@
+/*
+ * 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.api.code;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Represents some code installed in the code cache of the runtime.
+ * This encapsulated details are only for informational purposes.
+ * At any time, the runtime may invalidate the underlying code (e.g. due to deopt etc).
+ */
+public interface CodeInfo {
+
+    /**
+     * Gets the start address of this installed code.
+     */
+    long start();
+
+    /**
+     * Gets a copy of this installed code.
+     */
+    byte[] code();
+
+    /**
+     * Gets the method (if any) from which this installed code was compiled.
+     */
+    ResolvedJavaMethod method();
+}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationQueue.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationQueue.java	Wed Jul 18 10:50:57 2012 -0700
@@ -24,7 +24,10 @@
 
 import com.oracle.graal.api.meta.*;
 
+/**
+ * Callback mechanism for the VM to schedule a compilation.
+ */
+public interface CompilationQueue {
 
-public interface CompilationQueue {
     boolean enqueue(final ResolvedJavaMethod method, final int entryBCI, boolean blocking, int priority) throws Throwable;
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Wed Jul 18 10:50:57 2012 -0700
@@ -38,7 +38,7 @@
     private final BitSet frameRefMap;
 
     /**
-     * Creates a new {@code CiDebugInfo} from the given values.
+     * Creates a new {@link DebugInfo} from the given values.
      *
      * @param codePos the {@linkplain BytecodePosition code position} or {@linkplain BytecodeFrame frame} info
      * @param registerRefMap the register map
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,51 @@
+/*
+ * 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.api.code;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Represents a compiled instance of a method. It may have been invalidated or removed in the meantime.
+ */
+public interface InstalledCode {
+
+    public abstract class MethodInvalidatedException extends RuntimeException {
+
+        private static final long serialVersionUID = -3540232440794244844L;
+    }
+
+    /**
+     * Returns the method to which the compiled code belongs.
+     * @return the method to which the compiled code belongs.
+     */
+    ResolvedJavaMethod method();
+
+    /**
+     * @return true if the code represented by this object is still valid, false otherwise (may happen due to deopt, etc.)
+     */
+    boolean isValid();
+
+    Object execute(Object arg1, Object arg2, Object arg3);
+
+    Object executeVarargs(Object... args);
+}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java	Wed Jul 18 10:50:57 2012 -0700
@@ -104,7 +104,7 @@
     }
 
     /**
-     * Creates a {@code CiRegister} instance.
+     * Creates a {@link Register} instance.
      *
      * @param number unique identifier for the register
      * @param encoding the target machine encoding for the register
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java	Wed Jul 18 10:50:57 2012 -0700
@@ -25,8 +25,8 @@
 import com.oracle.graal.api.meta.*;
 
 /**
- * Denotes a register that stores a value of a fixed kind. There is exactly one (canonical) instance of {@code
- * CiRegisterValue} for each ({@link Register}, {@link Kind}) pair. Use {@link Register#asValue(Kind)} to
+ * Denotes a register that stores a value of a fixed kind. There is exactly one (canonical) instance of {@link
+ * RegisterValue} for each ({@link Register}, {@link Kind}) pair. Use {@link Register#asValue(Kind)} to
  * retrieve the canonical {@link RegisterValue} instance for a given (register,kind) pair.
  */
 public final class RegisterValue extends Value {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java	Wed Jul 18 10:50:57 2012 -0700
@@ -53,7 +53,7 @@
     public final int wordSize;
 
     /**
-     * The CiKind to be used for representing raw pointers and CPU registers.
+     * The kind to be used for representing raw pointers and CPU registers.
      */
     public final Kind wordKind;
 
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Wed Jul 18 10:50:57 2012 -0700
@@ -36,12 +36,17 @@
     private final int id;
 
     /**
-     * Creates a new CiVirtualObject for the given type, with the given fields. If the type is an instance class then the values array needs to have one entry for each field, ordered in
-     * like the fields returned by {@link ResolvedJavaType#declaredFields()}. If the type is an array then the length of the values array determines the reallocated array length.
-     * @param type the type of the object whose allocation was removed during compilation. This can be either an instance of an array type.
+     * Creates a new {@link VirtualObject} for the given type, with the given fields. If the type is an instance class
+     * then the values array needs to have one entry for each field, ordered in like the fields returned by
+     * {@link ResolvedJavaType#declaredFields()}. If the type is an array then the length of the values array determines
+     * the reallocated array length.
+     *
+     * @param type the type of the object whose allocation was removed during compilation. This can be either an
+     *            instance of an array type.
      * @param values an array containing all the values to be stored into the object when it is recreated.
-     * @param id a unique id that identifies the object within the debug information for one position in the compiled code.
-     * @return a new CiVirtualObject instance.
+     * @param id a unique id that identifies the object within the debug information for one position in the compiled
+     *            code.
+     * @return a new {@link VirtualObject} instance.
      */
     public static VirtualObject get(JavaType type, Value[] values, int id) {
         return new VirtualObject(type, values, id);
--- a/graal/com.oracle.graal.api.meta/overview.html	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/overview.html	Wed Jul 18 10:50:57 2012 -0700
@@ -30,7 +30,8 @@
 </head>
 <body>
 
-Documentation for the <code>com.oracle.graal.api.meta</code> project.
+The <code>com.oracle.graal.api.meta</code> project provides an API to the runtime data structures
+for various Java elements. It extends standard Java reflection in terms of the amount detail exposed.
 
 </body>
 </html>
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/CodeInfo.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +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.api.meta;
-
-/**
- * Represents some code installed in the code cache of the runtime.
- * This encapsulated details are only for informational purposes.
- * At any time, the runtime may invalidate the underlying code (e.g. due to deopt etc).
- */
-public interface CodeInfo {
-
-    /**
-     * Gets the start address of this installed code.
-     */
-    long start();
-
-    /**
-     * Gets a copy of this installed code.
-     */
-    byte[] code();
-
-    /**
-     * Gets the method (if any) from which this installed code was compiled.
-     */
-    ResolvedJavaMethod method();
-}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Wed Jul 18 10:50:57 2012 -0700
@@ -397,6 +397,7 @@
 
     /**
      * Creates a boxed object constant.
+     *
      * @param o the object value to box
      * @return a boxed copy of {@code value}
      */
@@ -410,8 +411,9 @@
     /**
      * Creates a boxed constant for the given kind from an Object.
      * The object needs to be of the Java boxed type corresponding to the kind.
+     *
      * @param kind the kind of the constant to create
-     * @param value the Java boxed value: a Byte instance for CiKind Byte, etc.
+     * @param value the Java boxed value: a {@link Byte} instance for {@link Kind#Byte}, etc.
      * @return the boxed copy of {@code value}
      */
     public static Constant forBoxed(Kind kind, Object value) {
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/InstalledCode.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * 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.api.meta;
-
-/**
- * Represents a compiled instance of a method. It may have been invalidated or removed in the meantime.
- */
-public interface InstalledCode {
-
-    public abstract class MethodInvalidatedException extends RuntimeException {
-
-        private static final long serialVersionUID = -3540232440794244844L;
-    }
-
-    /**
-     * Returns the method to which the compiled code belongs.
-     * @return the method to which the compiled code belongs.
-     */
-    ResolvedJavaMethod method();
-
-    /**
-     * @return true if the code represented by this object is still valid, false otherwise (may happen due to deopt, etc.)
-     */
-    boolean isValid();
-
-    Object execute(Object arg1, Object arg2, Object arg3);
-
-    Object executeVarargs(Object... args);
-}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Wed Jul 18 10:50:57 2012 -0700
@@ -264,16 +264,16 @@
                 if (value instanceof String) {
                     String s = (String) value;
                     if (s.length() > 50) {
-                        return "\"" + s.substring(0, 30) + "...\"";
+                        return "String:\"" + s.substring(0, 30) + "...\"";
                     } else {
-                        return " \"" + s + '"';
+                        return "String:\"" + s + '"';
                     }
                 } else if (value instanceof JavaType) {
-                    return "class " + MetaUtil.toJavaName((JavaType) value);
-                } else if (value instanceof Enum || value instanceof FormatWithToString) {
-                    return String.valueOf(value);
+                    return "JavaType:" + MetaUtil.toJavaName((JavaType) value);
+                } else if (value instanceof Enum || value instanceof FormatWithToString || value instanceof Number) {
+                    return MetaUtil.getSimpleName(value.getClass(), true) + ":" + String.valueOf(value);
                 } else if (value instanceof Class< ? >) {
-                    return ((Class< ? >) value).getName() + ".class";
+                    return "Class:" + ((Class< ? >) value).getName();
                 } else if (value.getClass().isArray()) {
                     return formatArray(value);
                 } else {
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Wed Jul 18 10:50:57 2012 -0700
@@ -369,7 +369,8 @@
      *     java.lang.String.valueOf(String.java:2930) [bci: 12]
      * </pre>
      *
-     * Otherwise, the string returned is the value of {@code CiUtil.format("%H.%n(%p)"}, suffixed by the bci location.
+     * Otherwise, the string returned is the value of applying {@link #format(String, JavaMethod)}
+     * with the format string {@code "%H.%n(%p)"}, suffixed by the bci location.
      * For example:
      *
      * <pre>
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java	Wed Jul 18 10:50:57 2012 -0700
@@ -31,7 +31,7 @@
     private static final long serialVersionUID = -6909397188697766469L;
 
     @SuppressWarnings("serial")
-    public static Value IllegalValue = new Value(Kind.Illegal) {
+    public static final Value IllegalValue = new Value(Kind.Illegal) {
         @Override
         public String toString() {
             return "-";
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Jul 18 10:50:57 2012 -0700
@@ -59,14 +59,14 @@
     /**
      * The XIR generator that lowers Java operations to machine operations.
      */
-    public final RiXirGenerator xir;
+    public final XirGenerator xir;
 
     /**
      * The backend that this compiler has been configured for.
      */
     public final Backend backend;
 
-    public GraalCompiler(GraalCodeCacheProvider runtime, TargetDescription target, Backend backend, RiXirGenerator xirGen) {
+    public GraalCompiler(GraalCodeCacheProvider runtime, TargetDescription target, Backend backend, XirGenerator xirGen) {
         this.runtime = runtime;
         this.target = target;
         this.xir = xirGen;
@@ -170,44 +170,46 @@
 
         new LoweringPhase(runtime, assumptions).apply(graph);
 
+        if (GraalOptions.OptTailDuplication) {
+            new TailDuplicationPhase().apply(graph);
+            if (GraalOptions.OptCanonicalizer) {
+                new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+            }
+        }
+
         if (GraalOptions.CullFrameStates) {
             new CullFrameStatesPhase().apply(graph);
         }
-        new FloatingReadPhase().apply(graph);
-        if (GraalOptions.OptGVN) {
-            new GlobalValueNumberingPhase().apply(graph);
-        }
-        if (GraalOptions.OptReadElimination) {
-            new ReadEliminationPhase().apply(graph);
+
+        if (GraalOptions.FloatingReads) {
+            int mark = graph.getMark();
+            new FloatingReadPhase().apply(graph);
+            new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph);
+            if (GraalOptions.OptReadElimination) {
+                new ReadEliminationPhase().apply(graph);
+            }
         }
 
         if (GraalOptions.PropagateTypes) {
             new PropagateTypeCachePhase(target, runtime, assumptions).apply(graph);
         }
 
+        if (GraalOptions.OptLoopTransform) {
+            new LoopTransformLowPhase().apply(graph);
+        }
+        new RemoveValueProxyPhase().apply(graph);
+
         if (GraalOptions.CheckCastElimination) {
             new CheckCastEliminationPhase().apply(graph);
         }
         if (GraalOptions.OptCanonicalizer) {
             new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
         }
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
-        }
-
-        if (GraalOptions.OptLoopTransform) {
-            new LoopTransformLowPhase().apply(graph);
-        }
-        new RemoveValueProxyPhase().apply(graph);
 
         plan.runPhases(PhasePosition.MID_LEVEL, graph);
 
         plan.runPhases(PhasePosition.LOW_LEVEL, graph);
 
-        new DeadCodeEliminationPhase().apply(graph);
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
-        }
         // Add safepoints to loops
         if (GraalOptions.GenLoopSafepoints) {
             new LoopSafepointInsertionPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Wed Jul 18 10:50:57 2012 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.compiler;
 
+import com.oracle.graal.nodes.*;
+
 
 /**
  * This class encapsulates options that control the behavior of the Graal compiler.
@@ -71,6 +73,9 @@
     public static int     ForcedInlineEscapeWeight           = 10;
     public static boolean PrintEscapeAnalysis                = ____;
 
+    public static double TailDuplicationProbability          = 0.5;
+    public static int    TailDuplicationTrivialSize          = 1;
+
     // absolute probability analysis
     public static boolean ProbabilityAnalysis                = true;
     public static int     LoopFrequencyPropagationPolicy     = -2;
@@ -135,11 +140,12 @@
     public static boolean DumpOnError                        = ____;
 
     // Ideal graph visualizer output settings
-    public static int     PlotLevel                          = 3;
-    public static int     PrintIdealGraphLevel               = 0;
+    public static boolean PrintBinaryGraphs                  = ____;
+    public static boolean PrintCFG                           = true;
     public static boolean PrintIdealGraphFile                = ____;
     public static String  PrintIdealGraphAddress             = "127.0.0.1";
     public static int     PrintIdealGraphPort                = 4444;
+    public static int     PrintBinaryGraphPort               = 4445;
 
     // Other printing settings
     public static boolean PrintQueue                         = ____;
@@ -175,7 +181,7 @@
     public static boolean GenSafepoints                      = true;
     public static boolean GenLoopSafepoints                  = true;
            static boolean UseTypeCheckHints                  = true;
-    public static boolean InlineVTableStubs                  = ____;
+    public static boolean InlineVTableStubs                  = true;
     public static boolean AlwaysInlineVTableStubs            = ____;
 
     public static boolean GenAssertionCode                   = ____;
@@ -210,6 +216,8 @@
     public static boolean OptLivenessAnalysis                = true;
     public static boolean OptLoopTransform                   = true;
     public static boolean OptSafepointElimination            = true;
+    public static boolean FloatingReads                      = true;
+    public static boolean OptTailDuplication                 = true;
 
     /**
      * Insert a counter in the method prologue to track the most frequently called methods that were compiled by Graal.
@@ -231,9 +239,9 @@
     public static boolean PrintFlags                           = false;
 
     /**
-     * Counts the various paths taken through a compiled checkcast.
+     * Counts the various paths taken through snippets.
      */
-    public static boolean CheckcastCounters = false;
+    public static boolean SnippetCounters = false;
 
     /**
      * If the probability that a checkcast will hit one the profiled types (up to {@link #CheckcastMaxHints})
@@ -266,6 +274,11 @@
     public static String HIRLowerNewInstance = "";
     public static String HIRLowerNewArray = "";
 
+    /**
+     * Use XIR to lower {@link Invoke} nodes.
+     */
+    public static boolean XIRLowerInvokes = false;
+
     static {
         // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this)
         assert (DetailedAsserts = true) == true;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ComputeLinearScanOrder.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ComputeLinearScanOrder.java	Wed Jul 18 10:50:57 2012 -0700
@@ -27,6 +27,7 @@
 
 import com.oracle.max.criutils.*;
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
@@ -304,15 +305,21 @@
             Block cur = workList.remove(workList.size() - 1);
             appendBlock(cur);
 
-            // make the most successor with the highest probability the immediate successor
             Node endNode = cur.getEndNode();
-            if (endNode instanceof IfNode && ((IfNode) endNode).probability() < 0.5) {
-                assert cur.numberOfSux() == 2;
-                if (readyForProcessing(cur.suxAt(1))) {
-                    sortIntoWorkList(cur.suxAt(1));
-                }
-                if (readyForProcessing(cur.suxAt(0))) {
-                    sortIntoWorkList(cur.suxAt(0));
+            if (endNode instanceof ControlSplitNode) {
+                // Sort the successors according to their probabilities:
+                final ControlSplitNode split = (ControlSplitNode) endNode;
+                Integer[] indexes = Util.createSortedPermutation(split.blockSuccessorCount(), new Comparator<Integer>() {
+                    @Override
+                    public int compare(Integer o1, Integer o2) {
+                        return split.probability(o1) < split.probability(o2) ? 1 : split.probability(o1) > split.probability(o2) ? -1 : 0;
+                    }
+                });
+                for (int index : indexes) {
+                    Block sux = cur.getSuccessors().get(indexes[index]);
+                    if (readyForProcessing(sux)) {
+                        sortIntoWorkList(sux);
+                    }
                 }
             } else {
                 for (Block sux : cur.getSuccessors()) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ControlFlowOptimizer.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ControlFlowOptimizer.java	Wed Jul 18 10:50:57 2012 -0700
@@ -211,7 +211,7 @@
                 // this may lead to unnecesary return instructions in the final code
 
                 assert curLastOp.info == null : "return instructions do not have debug information";
-                CiValue returnOpr = curLastOp.input(0);
+                Value returnOpr = curLastOp.input(0);
 
                 for (int j = block.numberOfPreds() - 1; j >= 0; j--) {
                     LIRBlock pred = block.predAt(j);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Wed Jul 18 10:50:57 2012 -0700
@@ -62,8 +62,8 @@
                 }
                 current = current.outerFrameState();
             } while (current != null);
-            // fill in the CiVirtualObject values:
-            // during this process new CiVirtualObjects might be discovered, so repeat until no more changes occur.
+            // fill in the VirtualObject values:
+            // during this process new VirtualObjects might be discovered, so repeat until no more changes occur.
             boolean changed;
             do {
                 changed = false;
@@ -73,7 +73,7 @@
                         VirtualObjectNode vobj = entry.getKey();
                         if (vobj instanceof BoxedVirtualObjectNode) {
                             BoxedVirtualObjectNode boxedVirtualObjectNode = (BoxedVirtualObjectNode) vobj;
-                            entry.getValue().setValues(new Value[]{toCiValue(boxedVirtualObjectNode.getUnboxedValue())});
+                            entry.getValue().setValues(new Value[]{toValue(boxedVirtualObjectNode.getUnboxedValue())});
                         } else {
                             Value[] values = new Value[vobj.fieldsCount()];
                             entry.getValue().setValues(values);
@@ -82,7 +82,7 @@
                                 VirtualObjectState currentField = objectStates.get(vobj);
                                 assert currentField != null;
                                 for (int i = 0; i < vobj.fieldsCount(); i++) {
-                                    values[i] = toCiValue(currentField.fieldValues().get(i));
+                                    values[i] = toValue(currentField.fieldValues().get(i));
                                 }
                             }
                         }
@@ -104,17 +104,17 @@
 
         Value[] values = new Value[numLocals + numStack + numLocks];
         for (int i = 0; i < numLocals; i++) {
-            values[i] = toCiValue(state.localAt(i));
+            values[i] = toValue(state.localAt(i));
         }
         for (int i = 0; i < numStack; i++) {
-            values[numLocals + i] = toCiValue(state.stackAt(i));
+            values[numLocals + i] = toValue(state.stackAt(i));
         }
 
         LockScope nextLock = locks;
         for (int i = numLocks - 1; i >= 0; i--) {
             assert locks != null && nextLock.inliningIdentifier == state.inliningIdentifier() && nextLock.stateDepth == i;
 
-            Value owner = toCiValue(nextLock.monitor.object());
+            Value owner = toValue(nextLock.monitor.object());
             Value lockData = nextLock.lockData;
             boolean eliminated = nextLock.monitor.eliminated();
             values[numLocals + numStack + nextLock.stateDepth] = new MonitorValue(owner, lockData, eliminated);
@@ -135,7 +135,7 @@
         return frame;
     }
 
-    private Value toCiValue(ValueNode value) {
+    private Value toValue(ValueNode value) {
         if (value instanceof VirtualObjectNode) {
             VirtualObjectNode obj = (VirtualObjectNode) value;
             VirtualObject ciObj = virtualObjects.get(value);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Jul 18 10:50:57 2012 -0700
@@ -44,6 +44,8 @@
 import com.oracle.graal.lir.StandardOp.ParametersOp;
 import com.oracle.graal.lir.StandardOp.PhiJumpOp;
 import com.oracle.graal.lir.StandardOp.PhiLabelOp;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.asm.TargetMethodAssembler.CallPositionListener;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.FrameState.InliningIdentifier;
@@ -55,14 +57,14 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.max.asm.*;
-import com.oracle.max.cri.xir.CiXirAssembler.XirConstant;
-import com.oracle.max.cri.xir.CiXirAssembler.XirInstruction;
-import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
-import com.oracle.max.cri.xir.CiXirAssembler.XirOperand;
-import com.oracle.max.cri.xir.CiXirAssembler.XirParameter;
-import com.oracle.max.cri.xir.CiXirAssembler.XirRegister;
-import com.oracle.max.cri.xir.CiXirAssembler.XirTemp;
 import com.oracle.max.cri.xir.*;
+import com.oracle.max.cri.xir.XirAssembler.XirConstant;
+import com.oracle.max.cri.xir.XirAssembler.XirInstruction;
+import com.oracle.max.cri.xir.XirAssembler.XirMark;
+import com.oracle.max.cri.xir.XirAssembler.XirOperand;
+import com.oracle.max.cri.xir.XirAssembler.XirParameter;
+import com.oracle.max.cri.xir.XirAssembler.XirRegister;
+import com.oracle.max.cri.xir.XirAssembler.XirTemp;
 import com.oracle.max.criutils.*;
 
 /**
@@ -78,7 +80,7 @@
 
     protected final LIR lir;
     protected final XirSupport xirSupport;
-    protected final RiXirGenerator xir;
+    protected final XirGenerator xir;
     private final DebugInfoBuilder debugInfoBuilder;
 
     private Block currentBlock;
@@ -142,7 +144,7 @@
     private LockScope curLocks;
 
 
-    public LIRGenerator(Graph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, RiXirGenerator xir, Assumptions assumptions) {
+    public LIRGenerator(Graph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, XirGenerator xir, Assumptions assumptions) {
         this.graph = graph;
         this.runtime = runtime;
         this.target = target;
@@ -343,6 +345,7 @@
             if (curLocks == null) {
                 curLocks = predLocks;
             } else if (curLocks != predLocks && (!pred.isLoopEnd() || predLocks != null)) {
+//                throw new GraalInternalError("cause: %s", predLocks);
                 throw new BailoutException("unbalanced monitors: predecessor blocks have different monitor states");
             }
         }
@@ -504,7 +507,7 @@
     }
 
     private static boolean canBeNullCheck(LocationNode location) {
-        // TODO: Make this part of CiTarget
+        // TODO: Make this part of TargetDescription
         return !(location instanceof IndexedLocationNode) && location.displacement() < 4096;
     }
 
@@ -899,15 +902,27 @@
             destinationAddress = emitXir(snippet, x.node(), addrInfo, false);
         }
 
+        final Map<XirMark, Mark> marks = snippet.marks;
+
+        CallPositionListener callPositionListener = new CallPositionListener() {
+            public void beforeCall(TargetMethodAssembler tasm) {
+            }
+            public void atCall(TargetMethodAssembler tasm) {
+                if (marks != null) {
+                    marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0]));
+                }
+            }
+        };
+
         LIRFrameState callInfo = stateFor(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null, x.leafGraphId());
-        emitCall(targetMethod, resultOperand, argList, destinationAddress, callInfo, snippet.marks);
+        emitCall(targetMethod, resultOperand, argList, destinationAddress, callInfo, callPositionListener);
 
         if (isLegal(resultOperand)) {
             setResult(x.node(), emitMove(resultOperand));
         }
     }
 
-    protected abstract void emitCall(Object targetMethod, Value result, List<Value> arguments, Value targetAddress, LIRFrameState info, Map<XirMark, Mark> marks);
+    protected abstract void emitCall(Object targetMethod, Value result, List<Value> arguments, Value targetAddress, LIRFrameState info, CallPositionListener ecl);
 
 
     private static Value toStackKind(Value value) {
@@ -1056,11 +1071,7 @@
 
     private void emitSequentialSwitch(final SwitchNode x, Variable key, LabelRef defaultTarget) {
         int keyCount = x.keyCount();
-        Integer[] indexes = new Integer[keyCount];
-        for (int i = 0; i < keyCount; i++) {
-            indexes[i] = i;
-        }
-        Arrays.sort(indexes, new Comparator<Integer>() {
+        Integer[] indexes = Util.createSortedPermutation(keyCount, new Comparator<Integer>() {
             @Override
             public int compare(Integer o1, Integer o2) {
                 return x.keyProbability(o1) < x.keyProbability(o2) ? 1 : x.keyProbability(o1) > x.keyProbability(o2) ? -1 : 0;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/graph/PostOrderNodeIterator.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/graph/PostOrderNodeIterator.java	Wed Jul 18 10:50:57 2012 -0700
@@ -27,6 +27,14 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
+/**
+ * A PostOrderNodeIterator iterates the fixed nodes of the graph in post order starting from a specified fixed node.<br>
+ * For this iterator the CFG is defined by the classical CFG nodes ({@link ControlSplitNode}, {@link MergeNode}...) and the {@link FixedWithNextNode#next() next} pointers
+ * of {@link FixedWithNextNode}.<br>
+ * While iterating it maintains a user-defined state by calling the methods available in {@link MergeableState}.
+ *
+ * @param <T> the type of {@link MergeableState} handled by this PostOrderNodeIterator
+ */
 public abstract class PostOrderNodeIterator<T extends MergeableState<T>> {
 
     private final NodeBitMap visitedEnds;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java	Wed Jul 18 10:50:57 2012 -0700
@@ -22,6 +22,9 @@
  */
 package com.oracle.graal.compiler.phases;
 
+import java.util.*;
+import java.util.concurrent.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
@@ -51,6 +54,7 @@
 
     private NodeWorkList workList;
     private Tool tool;
+    private List<Node> snapshotTemp;
 
     public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) {
         this(target, runtime, assumptions, null, 0, null);
@@ -82,6 +86,7 @@
         this.runtime = runtime;
         this.immutabilityPredicate = immutabilityPredicate;
         this.initWorkingSet = workingSet;
+        this.snapshotTemp = new ArrayList<>();
     }
 
     @Override
@@ -97,14 +102,6 @@
         }
         tool = new Tool(workList, runtime, target, assumptions, immutabilityPredicate);
         processWorkSet(graph);
-
-        while (graph.getUsagesDroppedNodesCount() > 0) {
-            for (Node n : graph.getAndCleanUsagesDroppedNodes()) {
-                if (!n.isDeleted() && n.usages().size() == 0 && GraphUtil.isFloatingNode().apply(n)) {
-                    n.safeDelete();
-                }
-            }
-        }
     }
 
     public interface IsImmutablePredicate {
@@ -138,8 +135,19 @@
                 return;
             }
             int mark = graph.getMark();
-            tryCanonicalize(node, graph, tool);
-            tryInferStamp(node, graph);
+            if (!tryKillUnused(node)) {
+                node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp);
+                if (!tryCanonicalize(node, graph, tool)) {
+                    tryInferStamp(node, graph);
+                } else {
+                    for (Node in : snapshotTemp) {
+                        if (in.isAlive() && in.usages().isEmpty()) {
+                            GraphUtil.killWithUnusedFloatingInputs(in);
+                        }
+                    }
+                }
+                snapshotTemp.clear();
+            }
 
             for (Node newNode : graph.getNewNodes(mark)) {
                 workList.add(newNode);
@@ -147,6 +155,14 @@
         }
     }
 
+    private static boolean tryKillUnused(Node node) {
+        if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) {
+            GraphUtil.killWithUnusedFloatingInputs(node);
+            return true;
+        }
+        return false;
+    }
+
     public static boolean tryGlobalValueNumbering(Node node, StructuredGraph graph) {
         if (node.getNodeClass().valueNumberable()) {
             Node newNode = graph.findDuplicate(node);
@@ -162,11 +178,11 @@
         return false;
     }
 
-    public static void tryCanonicalize(final Node node, final StructuredGraph graph, final SimplifierTool tool) {
+    public static boolean tryCanonicalize(final Node node, final StructuredGraph graph, final SimplifierTool tool) {
         if (node instanceof Canonicalizable) {
             METRIC_CANONICALIZATION_CONSIDERED_NODES.increment();
-            Debug.scope("CanonicalizeNode", node, new Runnable() {
-                public void run() {
+            return Debug.scope("CanonicalizeNode", node, new Callable<Boolean>(){
+                public Boolean call() {
                     ValueNode canonical = ((Canonicalizable) node).canonical(tool);
 //     cases:                                           original node:
 //                                         |Floating|Fixed-unconnected|Fixed-connected|
@@ -182,9 +198,9 @@
 //       X: must not happen (checked with assertions)
                     if (canonical == node) {
                         Debug.log("Canonicalizer: work on %s", node);
+                        return false;
                     } else {
                         Debug.log("Canonicalizer: replacing %s with %s", node, canonical);
-
                         METRIC_CANONICALIZED_NODES.increment();
                         if (node instanceof FloatingNode) {
                             if (canonical == null) {
@@ -192,7 +208,7 @@
                                 graph.removeFloating((FloatingNode) node);
                             } else {
                                 // case 2
-                                assert !(canonical instanceof FixedNode) || canonical.predecessor() != null : node + " -> " + canonical +
+                                assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode) : node + " -> " + canonical +
                                                 " : replacement should be floating or fixed and connected";
                                 graph.replaceFloating((FloatingNode) node, canonical);
                             }
@@ -218,6 +234,7 @@
                                 }
                             }
                         }
+                        return true;
                     }
                 }
             });
@@ -226,6 +243,7 @@
             METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment();
             ((Simplifiable) node).simplify(tool);
         }
+        return node.isDeleted();
     }
 
     /**
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CheckCastEliminationPhase.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CheckCastEliminationPhase.java	Wed Jul 18 10:50:57 2012 -0700
@@ -166,16 +166,16 @@
             // this piece of code handles phis (merges the types and knownNull/knownNotNull of the values)
             if (!(merge instanceof LoopBeginNode)) {
                 for (PhiNode phi : merge.phis()) {
-                    if (phi.type() == PhiType.Value && phi.kind() == CiKind.Object) {
+                    if (phi.type() == PhiType.Value && phi.kind() == Kind.Object) {
                         ValueNode firstValue = phi.valueAt(0);
-                        RiResolvedType type = getNodeType(firstValue);
+                        ResolvedJavaType type = getNodeType(firstValue);
                         boolean notNull = knownNotNull.contains(firstValue);
                         boolean nul = knownNull.contains(firstValue);
 
                         for (int i = 0; i < withStates.size(); i++) {
                             State otherState = withStates.get(i);
                             ValueNode value = phi.valueAt(i + 1);
-                            RiResolvedType otherType = otherState.getNodeType(value);
+                            ResolvedJavaType otherType = otherState.getNodeType(value);
                             type = widen(type, otherType);
                             notNull &= otherState.knownNotNull.contains(value);
                             nul &= otherState.knownNull.contains(value);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Wed Jul 18 10:50:57 2012 -0700
@@ -169,7 +169,7 @@
 
             if (virtual.fieldsCount() > 0) {
                 final BlockExitState startState = new BlockExitState(escapeFields, virtual);
-                final PostOrderNodeIterator<?> iterator = new PostOrderNodeIterator<BlockExitState>(next, startState) {
+                new PostOrderNodeIterator<BlockExitState>(next, startState) {
                     @Override
                     protected void node(FixedNode curNode) {
                         op.updateState(virtual, curNode, fields, state.fieldState);
@@ -183,8 +183,7 @@
                             ((StateSplit) curNode).stateAfter().addVirtualObjectMapping(v);
                         }
                     }
-                };
-                iterator.apply();
+                }.apply();
             }
         }
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java	Wed Jul 18 10:50:57 2012 -0700
@@ -24,308 +24,269 @@
 
 import java.util.*;
 
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.cfg.*;
+import com.oracle.graal.compiler.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.extended.*;
 
 public class FloatingReadPhase extends Phase {
 
-    private static class MemoryMap {
-        private Block block;
-        private IdentityHashMap<Object, Node> map;
-        private IdentityHashMap<Object, Node> loopEntryMap;
-        private int mergeOperationCount;
+    private IdentityHashMap<LoopBeginNode, List<MemoryMap>> loopEndStatesMap;
 
-        public MemoryMap(Block block) {
-            this.block = block;
-            map = new IdentityHashMap<>();
+    private static class LoopState {
+        public LoopBeginNode loopBegin;
+        public MemoryMap state;
+        public IdentityHashMap<PhiNode, Object> loopPhiLocations = new IdentityHashMap<>();
+        public ValueNode loopEntryAnyLocation;
+        public LoopState(LoopBeginNode loopBegin, MemoryMap state, ValueNode loopEntryAnyLocation) {
+            this.loopBegin = loopBegin;
+            this.state = state;
+            this.loopEntryAnyLocation = loopEntryAnyLocation;
         }
 
-        public MemoryMap(Block block, MemoryMap other) {
-            this(block);
-            map.putAll(other.map);
+        @Override
+        public String toString() {
+            return "State@" + loopBegin;
+        }
+    }
+
+    private class MemoryMap implements MergeableState<MemoryMap> {
+        private IdentityHashMap<Object, ValueNode> lastMemorySnapshot;
+        private LinkedList<LoopState> loops;
+
+        public MemoryMap(MemoryMap memoryMap) {
+            lastMemorySnapshot = new IdentityHashMap<>(memoryMap.lastMemorySnapshot);
+            loops = new LinkedList<>(memoryMap.loops);
         }
 
-        public void mergeLoopEntryWith(MemoryMap otherMemoryMap, LoopBeginNode begin, EndNode pred) {
-            for (Object keyInOther : otherMemoryMap.map.keySet()) {
-                assert loopEntryMap.containsKey(keyInOther) || map.get(keyInOther) == otherMemoryMap.map.get(keyInOther) : keyInOther + ", " + map.get(keyInOther) + " vs " + otherMemoryMap.map.get(keyInOther) + " " + begin;
+        public MemoryMap() {
+            lastMemorySnapshot = new IdentityHashMap<>();
+            loops = new LinkedList<>();
+        }
+
+        @Override
+        public String toString() {
+            return "Map=" + lastMemorySnapshot.toString() + " Loops=" + loops.toString();
+        }
+
+        @Override
+        public boolean merge(MergeNode merge, List<MemoryMap> withStates) {
+            if (withStates.size() == 0) {
+                return true;
             }
 
-            for (Map.Entry<Object, Node> entry : loopEntryMap.entrySet()) {
-                PhiNode phiNode = (PhiNode) entry.getValue();
-                Object key = entry.getKey();
-                Node other;
-                if (otherMemoryMap.map.containsKey(key)) {
-                    other = otherMemoryMap.map.get(key);
-                } else {
-                    other = otherMemoryMap.map.get(LocationNode.ANY_LOCATION);
-                }
-
-                // this explicitly honors the phi input index, since the iteration order will not always adhere to the end index ordering.
-                // TODO(ls) check for instances of this problem in other places.
-                int index = begin.phiPredecessorIndex(pred);
-                phiNode.initializeValueAt(index, (ValueNode) other);
-            }
-        }
-
-        public void mergeWith(MemoryMap otherMemoryMap, Block b) {
-            Debug.log("Merging block %s into block %s.", otherMemoryMap.block, block);
-            IdentityHashMap<Object, Node> otherMap = otherMemoryMap.map;
-
-            for (Map.Entry<Object, Node> entry : map.entrySet()) {
-                if (otherMap.containsKey(entry.getKey())) {
-                    mergeNodes(entry.getKey(), entry.getValue(), otherMap.get(entry.getKey()), b);
-                } else {
-                    mergeNodes(entry.getKey(), entry.getValue(), otherMap.get(LocationNode.ANY_LOCATION), b);
+            int minLoops = loops.size();
+            for (MemoryMap other : withStates) {
+                int otherLoops = other.loops.size();
+                if (otherLoops < minLoops) {
+                    minLoops = otherLoops;
                 }
             }
-
-            Node anyLocationNode = map.get(LocationNode.ANY_LOCATION);
-            for (Map.Entry<Object, Node> entry : otherMap.entrySet()) {
-                if (!map.containsKey(entry.getKey())) {
-                    Node current = anyLocationNode;
-                    if (anyLocationNode instanceof PhiNode) {
-                        PhiNode phiNode = (PhiNode) anyLocationNode;
-                        if (phiNode.merge() == block.getBeginNode()) {
-                            PhiNode phiCopy = (PhiNode) phiNode.copyWithInputs();
-                            phiCopy.removeInput(phiCopy.valueCount() - 1);
-                            current = phiCopy;
-                            map.put(entry.getKey(), current);
-                        }
-                    }
-                    mergeNodes(entry.getKey(), current, entry.getValue(), b);
+            while (loops.size() > minLoops) {
+                loops.pop();
+            }
+            for (MemoryMap other : withStates) {
+                while (other.loops.size() > minLoops) {
+                    other.loops.pop();
                 }
             }
 
-            mergeOperationCount++;
-        }
-
-        private void mergeNodes(Object location, Node original, Node newValue, Block mergeBlock) {
-            if (original == newValue) {
-                Debug.log("Nothing to merge both nodes are %s.", original);
-                return;
+            IdentityHashMap<Object, Object> keys = new IdentityHashMap<>();
+            for (Object key : lastMemorySnapshot.keySet()) {
+                keys.put(key, key);
             }
-            MergeNode m = (MergeNode) mergeBlock.getBeginNode();
-            if (m.isPhiAtMerge(original)) {
-                PhiNode phi = (PhiNode) original;
-                phi.addInput((ValueNode) newValue);
-                Debug.log("Add new input to %s: %s.", original, newValue);
-                assert phi.valueCount() <= phi.merge().forwardEndCount() : phi.merge();
-            } else {
-                PhiNode phi = m.graph().unique(new PhiNode(PhiType.Memory, m));
-                // TODO(ls) how does this work? add documentation ...
-                for (int i = 0; i < mergeOperationCount + 1; ++i) {
-                    phi.addInput((ValueNode) original);
+            for (MemoryMap other : withStates) {
+                assert other.loops.size() == loops.size();
+                assert other.loops.size() < 1 || other.loops.peek().loopBegin == loops.peek().loopBegin;
+                for (Object key : other.lastMemorySnapshot.keySet()) {
+                    keys.put(key, key);
+                }
+            }
+
+            for (Object key : keys.keySet()) {
+                ValueNode merged = lastMemorySnapshot.get(key);
+                if (merged == null) {
+                    merged = lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
                 }
-                phi.addInput((ValueNode) newValue);
-                Debug.log("Creating new %s merge=%s newValue=%s location=%s.", phi, phi.merge(), newValue, location);
-                assert phi.valueCount() <= phi.merge().forwardEndCount() + ((phi.merge() instanceof LoopBeginNode) ? 1 : 0) : phi.merge() + "/" + phi.valueCount() + "/" + phi.merge().forwardEndCount() + "/" + mergeOperationCount;
-                assert m.usages().contains(phi);
-                assert phi.merge().usages().contains(phi);
-                for (Node input : phi.inputs()) {
-                    assert input.usages().contains(phi);
+                Iterator<MemoryMap> it = withStates.iterator();
+                int i = 1;
+                boolean isPhi = false;
+                while (it.hasNext()) {
+                    MemoryMap other = it.next();
+                    ValueNode otherValue = other.lastMemorySnapshot.get(key);
+                    if (otherValue == null) {
+                        otherValue = other.lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
+                    }
+                    if (isPhi) {
+                        ((PhiNode) merged).addInput(otherValue);
+                    } else if (merged != otherValue) {
+                        PhiNode phi = merge.graph().add(new PhiNode(PhiType.Memory, merge));
+                        for (int j = 0; j < i; j++) {
+                            phi.addInput(merged);
+                        }
+                        phi.addInput(otherValue);
+                        merged = phi;
+                        isPhi = true;
+                        lastMemorySnapshot.put(key, phi);
+                    }
+                    i++;
                 }
-                map.put(location, phi);
             }
-        }
-
-        public void processCheckpoint(MemoryCheckpoint checkpoint) {
-            map.clear();
-            map.put(LocationNode.ANY_LOCATION, (Node) checkpoint);
-        }
-
-        public void processWrite(WriteNode writeNode) {
-            if (writeNode.location().locationIdentity() == LocationNode.ANY_LOCATION) {
-                map.clear();
-            }
-            map.put(writeNode.location().locationIdentity(), writeNode);
+            return true;
         }
 
-        public void processRead(ReadNode readNode) {
-            StructuredGraph graph = (StructuredGraph) readNode.graph();
-            assert readNode.getNullCheck() == false;
-
-            Debug.log("Register read to node %s.", readNode);
-            FloatingReadNode floatingRead;
-            if (readNode.location().locationIdentity() == LocationNode.FINAL_LOCATION) {
-                floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), null, readNode.stamp(), readNode.dependencies()));
-            } else {
-                floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), getLocationForRead(readNode), readNode.stamp(), readNode.dependencies()));
+        @Override
+        public void loopBegin(LoopBeginNode loopBegin) {
+            LoopState loopState = new LoopState(loopBegin, this, lastMemorySnapshot.get(LocationNode.ANY_LOCATION));
+            for (Map.Entry<Object, ValueNode> entry : lastMemorySnapshot.entrySet()) {
+                PhiNode phi = loopBegin.graph().add(new PhiNode(PhiType.Memory, loopBegin));
+                phi.addInput(entry.getValue());
+                entry.setValue(phi);
+                loopState.loopPhiLocations.put(phi, entry.getKey());
             }
-            floatingRead.setNullCheck(readNode.getNullCheck());
-            ValueAnchorNode anchor = null;
-            for (GuardNode guard : readNode.dependencies().filter(GuardNode.class)) {
-                if (anchor == null) {
-                    anchor = graph.add(new ValueAnchorNode());
-                }
-                anchor.addAnchoredNode(guard);
-            }
-            if (anchor != null) {
-                graph.addAfterFixed(readNode, anchor);
-            }
-            graph.replaceFixedWithFloating(readNode, floatingRead);
-        }
-
-        private Node getLocationForRead(ReadNode readNode) {
-            Object locationIdentity = readNode.location().locationIdentity();
-            Node result = map.get(locationIdentity);
-            if (result == null) {
-                result = map.get(LocationNode.ANY_LOCATION);
-            }
-            return result;
+            loops.push(loopState);
         }
 
-        public void createLoopEntryMemoryMap(Set<Object> modifiedLocations, Loop loop) {
-
-            loopEntryMap = new IdentityHashMap<>();
-
-            for (Object modifiedLocation : modifiedLocations) {
-                Node other;
-                if (map.containsKey(modifiedLocation)) {
-                    other = map.get(modifiedLocation);
-                } else {
-                    other = map.get(LocationNode.ANY_LOCATION);
-                }
-                createLoopEntryPhi(modifiedLocation, other, loop);
-            }
-
-            if (modifiedLocations.contains(LocationNode.ANY_LOCATION)) {
-                for (Map.Entry<Object, Node> entry : map.entrySet()) {
-                    if (!modifiedLocations.contains(entry.getKey())) {
-                        createLoopEntryPhi(entry.getKey(), entry.getValue(), loop);
-                    }
-                }
-            }
+        @Override
+        public void loopEnds(LoopBeginNode loopBegin, List<MemoryMap> loopEndStates) {
+            loopEndStatesMap.put(loopBegin, loopEndStates);
+            tryFinishLoopPhis(this, loopBegin);
         }
 
-        private void createLoopEntryPhi(Object modifiedLocation, Node other, Loop loop) {
-            PhiNode phi = other.graph().unique(new PhiNode(PhiType.Memory, (MergeNode) loop.header.getBeginNode()));
-            phi.addInput((ValueNode) other);
-            map.put(modifiedLocation, phi);
-            loopEntryMap.put(modifiedLocation, phi);
+        @Override
+        public void afterSplit(FixedNode node) {
+            // nothing
         }
 
-
-        public IdentityHashMap<Object, Node> getLoopEntryMap() {
-            return loopEntryMap;
+        @Override
+        public MemoryMap clone() {
+            return new MemoryMap(this);
         }
     }
 
     @Override
     protected void run(StructuredGraph graph) {
-
-        // Add start node write checkpoint.
-        addStartCheckpoint(graph);
-
-        // Identify blocks.
-        ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
-        Block[] blocks = cfg.getBlocks();
-
-        HashMap<Loop, Set<Object>> modifiedValues = new HashMap<>();
-        // Initialize modified values to empty hash set.
-        for (Loop loop : cfg.getLoops()) {
-            modifiedValues.put(loop, new HashSet<>());
-        }
-
-        // Get modified values in loops.
-        for (Node n : graph.getNodes()) {
-            Block block = cfg.blockFor(n);
-            if (block != null && block.getLoop() != null) {
-                if (n instanceof WriteNode) {
-                    WriteNode writeNode = (WriteNode) n;
-                    traceWrite(block.getLoop(), writeNode.location().locationIdentity(), modifiedValues);
-                } else if (n instanceof MemoryCheckpoint) {
-                    traceMemoryCheckpoint(block.getLoop(), modifiedValues);
-                }
+        loopEndStatesMap = new IdentityHashMap<>();
+        new PostOrderNodeIterator<MemoryMap>(graph.start(), new MemoryMap()) {
+            @Override
+            protected void node(FixedNode node) {
+                processNode(node, state);
             }
-        }
-
-        // Propagate values to parent loops.
-        for (Loop loop : cfg.getLoops()) {
-            if (loop.depth == 1) {
-                propagateFromChildren(loop, modifiedValues);
-            }
-        }
-
-        Debug.log("Modified values: %s.", modifiedValues);
-
-
-        // Process blocks (predecessors first).
-        MemoryMap[] memoryMaps = new MemoryMap[blocks.length];
-        for (final Block b : blocks) {
-            processBlock(b, memoryMaps, cfg.getNodeToBlock(), modifiedValues);
-        }
+        }.apply();
     }
 
-    private static void addStartCheckpoint(StructuredGraph graph) {
-        BeginNode entryPoint = graph.start();
-        FixedNode next = entryPoint.next();
-        if (!(next instanceof MemoryCheckpoint)) {
-            graph.addAfterFixed(entryPoint, graph.add(new WriteMemoryCheckpointNode()));
+    private void processNode(FixedNode node, MemoryMap state) {
+        if (node instanceof ReadNode) {
+            processRead((ReadNode) node, state);
+        } else if (node instanceof WriteNode) {
+            processWrite((WriteNode) node, state);
+        } else if (node instanceof MemoryCheckpoint) {
+            processCheckpoint((MemoryCheckpoint) node, state);
+        } else if (node instanceof LoopExitNode) {
+            processLoopExit((LoopExitNode) node, state);
         }
     }
 
-    private static void processBlock(Block b, MemoryMap[] memoryMaps, NodeMap<Block> nodeToBlock, HashMap<Loop, Set<Object>> modifiedValues) {
-        // Create initial memory map for the block.
-        MemoryMap map = null;
-        if (b.getPredecessors().size() == 0) {
-            map = new MemoryMap(b);
+    private static void processCheckpoint(MemoryCheckpoint checkpoint, MemoryMap state) {
+        processAnyLocationWrite((ValueNode) checkpoint, state);
+    }
+
+    private static void processWrite(WriteNode writeNode, MemoryMap state) {
+        if (writeNode.location().locationIdentity() == LocationNode.ANY_LOCATION) {
+            processAnyLocationWrite(writeNode, state);
+        }
+        state.lastMemorySnapshot.put(writeNode.location().locationIdentity(), writeNode);
+    }
+
+    private static void processAnyLocationWrite(ValueNode modifiying, MemoryMap state) {
+        for (Map.Entry<Object, ValueNode> entry : state.lastMemorySnapshot.entrySet()) {
+            entry.setValue(modifiying);
+        }
+        state.lastMemorySnapshot.put(LocationNode.ANY_LOCATION, modifiying);
+        state.loops.clear();
+    }
+
+    private void processRead(ReadNode readNode, MemoryMap state) {
+        StructuredGraph graph = (StructuredGraph) readNode.graph();
+        assert readNode.getNullCheck() == false;
+        Object locationIdentity = readNode.location().locationIdentity();
+        ValueNode lastLocationAccess = getLastLocationAccessForRead(state, locationIdentity);
+        FloatingReadNode floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), lastLocationAccess, readNode.stamp(), readNode.dependencies()));
+        floatingRead.setNullCheck(readNode.getNullCheck());
+        ValueAnchorNode anchor = null;
+        for (GuardNode guard : readNode.dependencies().filter(GuardNode.class)) {
+            if (anchor == null) {
+                anchor = graph.add(new ValueAnchorNode());
+            }
+            anchor.addAnchoredNode(guard);
+        }
+        if (anchor != null) {
+            graph.addAfterFixed(readNode, anchor);
+        }
+        graph.replaceFixedWithFloating(readNode, floatingRead);
+    }
+
+    private ValueNode getLastLocationAccessForRead(MemoryMap state, Object locationIdentity) {
+        ValueNode lastLocationAccess;
+        if (locationIdentity == LocationNode.FINAL_LOCATION) {
+            lastLocationAccess = null;
         } else {
-            map = new MemoryMap(b, memoryMaps[b.getPredecessors().get(0).getId()]);
-            if (b.isLoopHeader()) {
-                Loop loop = b.getLoop();
-                map.createLoopEntryMemoryMap(modifiedValues.get(loop), loop);
+            lastLocationAccess = state.lastMemorySnapshot.get(locationIdentity);
+            if (lastLocationAccess == null) {
+                LoopState lastLoop = state.loops.peek();
+                if (lastLoop == null) {
+                    lastLocationAccess = state.lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
+                } else {
+                    ValueNode phiInit;
+                    if (state.loops.size() > 1) {
+                        phiInit = getLastLocationAccessForRead(state.loops.get(1).state, locationIdentity);
+                    } else {
+                        phiInit = lastLoop.loopEntryAnyLocation;
+                    }
+                    PhiNode phi = lastLoop.loopBegin.graph().add(new PhiNode(PhiType.Memory, lastLoop.loopBegin));
+                    phi.addInput(phiInit);
+                    lastLoop.state.lastMemorySnapshot.put(locationIdentity, phi);
+                    lastLoop.loopPhiLocations.put(phi, locationIdentity);
+                    tryFinishLoopPhis(lastLoop.state, lastLoop.loopBegin);
+                    lastLocationAccess = phi;
+                }
+                state.lastMemorySnapshot.put(locationIdentity, lastLocationAccess);
             }
-            for (int i = 1; i < b.getPredecessors().size(); ++i) {
-                Block block = b.getPredecessors().get(i);
-                if (!block.isLoopEnd()) {
-                    map.mergeWith(memoryMaps[block.getId()], b);
+        }
+        return lastLocationAccess;
+    }
+
+    private static void processLoopExit(LoopExitNode exit, MemoryMap state) {
+        for (Map.Entry<Object, ValueNode> entry : state.lastMemorySnapshot.entrySet()) {
+            entry.setValue(exit.graph().unique(new ValueProxyNode(entry.getValue(), exit, PhiType.Memory)));
+        }
+        if (!state.loops.isEmpty()) {
+            state.loops.pop();
+        }
+    }
+
+    private void tryFinishLoopPhis(MemoryMap loopMemory, LoopBeginNode loopBegin) {
+        List<MemoryMap> loopEndStates = loopEndStatesMap.get(loopBegin);
+        if (loopEndStates == null) {
+            return;
+        }
+        LoopState loopState = loopMemory.loops.get(0);
+        int i = 0;
+        while (loopState.loopBegin != loopBegin) {
+            loopState = loopMemory.loops.get(++i);
+        }
+        for (PhiNode phi : loopBegin.phis()) {
+            if (phi.type() == PhiType.Memory && phi.valueCount() == 1) {
+                Object location = loopState.loopPhiLocations.get(phi);
+                assert location != null : "unknown location for " + phi;
+                for (MemoryMap endState : loopEndStates) {
+                    ValueNode otherNode = endState.lastMemorySnapshot.get(location);
+                    if (otherNode == null) {
+                        otherNode = endState.lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
+                    }
+                    phi.addInput(otherNode);
                 }
             }
         }
-        memoryMaps[b.getId()] = map;
-
-        // Process instructions of this block.
-        for (Node n : b.getNodes()) {
-            if (n instanceof ReadNode) {
-                ReadNode readNode = (ReadNode) n;
-                map.processRead(readNode);
-            } else if (n instanceof WriteNode) {
-                WriteNode writeNode = (WriteNode) n;
-                map.processWrite(writeNode);
-            } else if (n instanceof MemoryCheckpoint) {
-                MemoryCheckpoint checkpoint = (MemoryCheckpoint) n;
-                map.processCheckpoint(checkpoint);
-            }
-        }
-
-
-        if (b.getEndNode() instanceof LoopEndNode) {
-            LoopEndNode end = (LoopEndNode) b.getEndNode();
-            LoopBeginNode begin = end.loopBegin();
-            Block beginBlock = nodeToBlock.get(begin);
-            MemoryMap memoryMap = memoryMaps[beginBlock.getId()];
-            assert memoryMap != null;
-            assert memoryMap.getLoopEntryMap() != null;
-            memoryMap.mergeLoopEntryWith(map, begin, (EndNode) b.getEndNode());
-        }
-    }
-
-    private static void traceMemoryCheckpoint(Loop loop, HashMap<Loop, Set<Object>> modifiedValues) {
-        modifiedValues.get(loop).add(LocationNode.ANY_LOCATION);
-    }
-
-    private void propagateFromChildren(Loop loop, HashMap<Loop, Set<Object>> modifiedValues) {
-        for (Loop child : loop.children) {
-            propagateFromChildren(child, modifiedValues);
-            modifiedValues.get(loop).addAll(modifiedValues.get(child));
-        }
-    }
-
-    private static void traceWrite(Loop loop, Object locationIdentity, HashMap<Loop, Set<Object>> modifiedValues) {
-        modifiedValues.get(loop).add(locationIdentity);
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java	Wed Jul 18 10:50:57 2012 -0700
@@ -84,10 +84,10 @@
         graph.createNodeMap();
 
         if (hints != null) {
-            scanInvokes((Iterable<? extends Node>) Util.uncheckedCast(this.hints), -1);
+            scanInvokes((Iterable<? extends Node>) Util.uncheckedCast(this.hints));
         } else {
-            scanInvokes(graph.getNodes(InvokeNode.class), 0);
-            scanInvokes(graph.getNodes(InvokeWithExceptionNode.class), 0);
+            scanInvokes(graph.getNodes(InvokeNode.class));
+            scanInvokes(graph.getNodes(InvokeWithExceptionNode.class));
         }
 
         while (!inlineCandidates.isEmpty() && graph.getNodeCount() < GraalOptions.MaximumDesiredSize) {
@@ -131,7 +131,7 @@
                 }
 
                 if (newNodes != null && info.level < GraalOptions.MaximumInlineLevel) {
-                    scanInvokes(newNodes, info.level + 1);
+                    scanInvokes(newNodes);
                 }
             }
         }
@@ -149,17 +149,17 @@
         }
     }
 
-    private void scanInvokes(final Iterable<? extends Node> nodes, final int level) {
+    private void scanInvokes(final Iterable<? extends Node> nodes) {
         Debug.scope("InliningDecisions", new Runnable() {
             public void run() {
                 for (Node node : nodes) {
                     if (node != null) {
                         if (node instanceof Invoke) {
                             Invoke invoke = (Invoke) node;
-                            scanInvoke(invoke, level);
+                            scanInvoke(invoke);
                         }
                         for (Node usage : node.usages().filterInterface(Invoke.class).snapshot()) {
-                            scanInvoke((Invoke) usage, level);
+                            scanInvoke((Invoke) usage);
                         }
                     }
                 }
@@ -167,10 +167,9 @@
         });
     }
 
-    private void scanInvoke(Invoke invoke, int level) {
-        InlineInfo info = InliningUtil.getInlineInfo(invoke, level >= 0 ? level : computeInliningLevel(invoke), runtime, assumptions, this, optimisticOpts);
+    private void scanInvoke(Invoke invoke) {
+        InlineInfo info = InliningUtil.getInlineInfo(invoke, computeInliningLevel(invoke), runtime, assumptions, this, optimisticOpts);
         if (info != null) {
-            assert level == -1 || computeInliningLevel(invoke) == level : "outer FramesStates must match inlining level";
             metricInliningConsidered.increment();
             inlineCandidates.add(info);
         }
@@ -260,13 +259,13 @@
     }
 
     private static int computeInliningLevel(Invoke invoke) {
-        int count = 0;
+        int count = -1;
         FrameState curState = invoke.stateAfter();
         while (curState != null) {
             count++;
             curState = curState.outerFrameState();
         }
-        return count - 1;
+        return count;
     }
 
     private static InliningPolicy createInliningPolicy() {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ReadEliminationPhase.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ReadEliminationPhase.java	Wed Jul 18 10:50:57 2012 -0700
@@ -22,26 +22,80 @@
  */
 package com.oracle.graal.compiler.phases;
 
+import java.util.*;
+
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
 public class ReadEliminationPhase extends Phase {
+    private Queue<PhiNode> newPhis;
 
     @Override
     protected void run(StructuredGraph graph) {
+        newPhis = new LinkedList<>();
         for (FloatingReadNode n : graph.getNodes(FloatingReadNode.class)) {
-            if (n.lastLocationAccess() != null) {
-                Node memoryInput = n.lastLocationAccess();
-                if (memoryInput instanceof WriteNode) {
-                    WriteNode other = (WriteNode) memoryInput;
-                    if (other.object() == n.object() && other.location() == n.location()) {
-                        Debug.log("Eliminated memory read %1.1s and replaced with node %s", n, other.value());
-                        graph.replaceFloating(n, other.value());
-                    }
-                }
+            if (isReadEliminable(n)) {
+                NodeMap<ValueNode> nodeMap = n.graph().createNodeMap();
+                ValueNode value = getValue(n, n.lastLocationAccess(), nodeMap);
+                Debug.log("Eliminated memory read %1.1s and replaced with node %s", n, value);
+                graph.replaceFloating(n, value);
             }
         }
     }
+
+    private boolean isReadEliminable(FloatingReadNode n) {
+        return isWrites(n, n.lastLocationAccess(), n.graph().createNodeBitMap());
+    }
+
+    private boolean isWrites(FloatingReadNode n, Node lastLocationAccess, NodeBitMap visited) {
+        if (lastLocationAccess == null) {
+            return false;
+        }
+        if (visited.isMarked(lastLocationAccess)) {
+            return true; // dataflow loops must come from Phis assume them ok until proven wrong
+        }
+        if (lastLocationAccess instanceof ValueProxyNode) {
+            return isWrites(n, ((ValueProxyNode) lastLocationAccess).value(), visited);
+        }
+        if (lastLocationAccess instanceof WriteNode) {
+            WriteNode other = (WriteNode) lastLocationAccess;
+            return other.object() == n.object() && other.location() == n.location();
+        }
+        if (lastLocationAccess instanceof PhiNode) {
+            visited.mark(lastLocationAccess);
+            for (ValueNode value : ((PhiNode) lastLocationAccess).values()) {
+                if (!isWrites(n, value, visited)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    private ValueNode getValue(FloatingReadNode n, Node lastLocationAccess, NodeMap<ValueNode> nodeMap) {
+        ValueNode exisiting = nodeMap.get(lastLocationAccess);
+        if (exisiting != null) {
+            return exisiting;
+        }
+        if (lastLocationAccess instanceof ValueProxyNode) {
+            return getValue(n, ((ValueProxyNode) lastLocationAccess).value(), nodeMap);
+        }
+        if (lastLocationAccess instanceof WriteNode) {
+            return ((WriteNode) lastLocationAccess).value();
+        }
+        if (lastLocationAccess instanceof PhiNode) {
+            PhiNode phi = (PhiNode) lastLocationAccess;
+            PhiNode newPhi = phi.graph().add(new PhiNode(n.kind(), phi.merge()));
+            nodeMap.set(lastLocationAccess, newPhi);
+            for (ValueNode value : phi.values()) {
+                newPhi.addInput(getValue(n, value, nodeMap));
+            }
+            newPhis.add(newPhi);
+            return newPhi;
+        }
+        throw GraalInternalError.shouldNotReachHere();
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/TailDuplicationPhase.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,524 @@
+/*
+ * 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.compiler.phases;
+
+import java.util.*;
+
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.Graph.DuplicationReplacement;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.VirtualState.NodeClosure;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
+
+/**
+ * This class is a phase that looks for opportunities for tail duplication. The static method
+ * {@link #tailDuplicate(MergeNode, TailDuplicationDecision, List)} can also be used to drive tail duplication from
+ * other places, e.g., inlining.
+ */
+public class TailDuplicationPhase extends Phase {
+
+    /*
+     * Various metrics on the circumstances in which tail duplication was/wasn't performed.
+     */
+    private static final DebugMetric metricDuplicationMonitors = Debug.metric("DuplicationMonitors");
+    private static final DebugMetric metricDuplicationEnd = Debug.metric("DuplicationEnd");
+    private static final DebugMetric metricDuplicationEndPerformed = Debug.metric("DuplicationEndPerformed");
+    private static final DebugMetric metricDuplicationOther = Debug.metric("DuplicationOther");
+    private static final DebugMetric metricDuplicationOtherPerformed = Debug.metric("DuplicationOtherPerformed");
+
+    /**
+     * This interface is used by tail duplication to let clients decide if tail duplication should be performed.
+     */
+    public interface TailDuplicationDecision {
+
+        /**
+         * Queries if tail duplication should be performed at the given merge. If this method returns true then the tail
+         * duplication will be performed, because all other checks have happened before.
+         *
+         * @param merge The merge at which tail duplication can be performed.
+         * @param fixedNodeCount The size of the set of fixed nodes that forms the base for the duplicated set of nodes.
+         * @return true if the tail duplication should be performed, false otherwise.
+         */
+        boolean doTransform(MergeNode merge, int fixedNodeCount);
+    }
+
+    /**
+     * A tail duplication decision closure that employs the default algorithm: Check if there are any phis on the merge
+     * whose stamps improve and that have usages within the duplicated set of fixed nodes.
+     */
+    public static final TailDuplicationDecision DEFAULT_DECISION = new TailDuplicationDecision() {
+
+        public boolean doTransform(MergeNode merge, int fixedNodeCount) {
+            if (fixedNodeCount < GraalOptions.TailDuplicationTrivialSize) {
+                return true;
+            }
+            HashSet<PhiNode> improvements = new HashSet<>();
+            for (PhiNode phi : merge.phis()) {
+                Stamp phiStamp = phi.stamp();
+                for (ValueNode input : phi.values()) {
+                    if (!input.stamp().equals(phiStamp)) {
+                        improvements.add(phi);
+                        break;
+                    }
+                }
+            }
+            if (improvements.isEmpty()) {
+                return false;
+            }
+            FixedNode current = merge;
+            int opportunities = 0;
+            while (current instanceof FixedWithNextNode) {
+                current = ((FixedWithNextNode) current).next();
+                for (PhiNode phi : improvements) {
+                    if (current.inputs().contains(phi)) {
+                        opportunities++;
+                    }
+                }
+            }
+            return opportunities > 0;
+        }
+    };
+
+    /**
+     * A tail duplication decision closure that always returns true.
+     */
+    public static final TailDuplicationDecision TRUE_DECISION = new TailDuplicationDecision() {
+
+        @Override
+        public boolean doTransform(MergeNode merge, int fixedNodeCount) {
+            return true;
+        }
+    };
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        // A snapshot is taken here, so that new MergeNode instances aren't considered for tail duplication.
+        for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) {
+            if (!(merge instanceof LoopBeginNode) && merge.probability() >= GraalOptions.TailDuplicationProbability) {
+                tailDuplicate(merge, DEFAULT_DECISION, null);
+            }
+        }
+    }
+
+    /**
+     * This method attempts to duplicate the tail of the given merge. The merge must not be a {@link LoopBeginNode}. If
+     * the merge is eligible for duplication (at least one fixed node in its tail, no {@link MonitorEnterNode}/
+     * {@link MonitorExitNode}, non-null {@link MergeNode#stateAfter()}) then the decision callback is used to determine
+     * whether the tail duplication should actually be performed. If replacements is non-null, then this list of
+     * {@link PiNode}s is used to replace one value per merge end.
+     *
+     * @param merge The merge whose tail should be duplicated.
+     * @param decision A callback that can make the final decision if tail duplication should occur or not.
+     * @param replacements A list of {@link PiNode}s, or null. If this list is non-null then its size needs to match the
+     *            merge's end count. Each entry can either be null or a {@link PiNode}, and is used to replace
+     *            {@link PiNode#object()} with the {@link PiNode} in the duplicated branch that corresponds to the
+     *            entry.
+     */
+    public static void tailDuplicate(MergeNode merge, TailDuplicationDecision decision, List<PiNode> replacements) {
+        assert !(merge instanceof LoopBeginNode);
+        assert replacements == null || replacements.size() == merge.forwardEndCount();
+        FixedNode fixed = merge;
+        int fixedCount = 0;
+        boolean containsMonitor = false;
+        while (fixed instanceof FixedWithNextNode) {
+            if (fixed instanceof MonitorEnterNode || fixed instanceof MonitorExitNode) {
+                containsMonitor = true;
+            }
+            fixed = ((FixedWithNextNode) fixed).next();
+            fixedCount++;
+        }
+        if (containsMonitor) {
+            // cannot currently be handled
+            // TODO (ls) re-evaluate this limitation after changes to the lock representation and the LIR generator
+            metricDuplicationMonitors.increment();
+        } else if (fixedCount > 1) {
+            if (fixed instanceof EndNode && !(((EndNode) fixed).merge() instanceof LoopBeginNode)) {
+                metricDuplicationEnd.increment();
+                if (decision.doTransform(merge, fixedCount)) {
+                    metricDuplicationEndPerformed.increment();
+                    new DuplicationOperation(merge, replacements).duplicate();
+                }
+            } else if (merge.stateAfter() != null) {
+                metricDuplicationOther.increment();
+                if (decision.doTransform(merge, fixedCount)) {
+                    metricDuplicationOtherPerformed.increment();
+                    new DuplicationOperation(merge, replacements).duplicate();
+                }
+            }
+        }
+    }
+
+    /**
+     * This class encapsulates one tail duplication operation on a specific {@link MergeNode}.
+     */
+    private static class DuplicationOperation {
+
+        private final MergeNode merge;
+        private final StructuredGraph graph;
+
+        private final HashMap<ValueNode, PhiNode> bottomPhis = new HashMap<>();
+        private final List<PiNode> replacements;
+
+        /**
+         * Initializes the tail duplication operation without actually performing any work.
+         *
+         * @param merge The merge whose tail should be duplicated.
+         * @param replacements A list of replacement {@link PiNode}s, or null. If this is non-null, then the size of the
+         *            list needs to match the number of end nodes at the merge.
+         */
+        public DuplicationOperation(MergeNode merge, List<PiNode> replacements) {
+            this.merge = merge;
+            this.replacements = replacements;
+            this.graph = (StructuredGraph) merge.graph();
+        }
+
+        /**
+         * Performs the actual tail duplication:
+         * <ul>
+         * <li>Creates a new {@link ValueAnchorNode} at the beginning of the duplicated area, an transfers all
+         * dependencies from the merge to this anchor.</li>
+         * <li>Determines the set of fixed nodes to be duplicated.</li>
+         * <li>Creates the new merge at the bottom of the duplicated area.</li>
+         * <li>Determines the complete set of duplicated nodes.</li>
+         * <li>Performs the actual duplication.</li>
+         * </ul>
+         */
+        private void duplicate() {
+            Debug.log("tail duplication at merge %s in %s (prob %f)", merge, graph.method(), merge.probability());
+
+            ValueAnchorNode anchor = addValueAnchor();
+
+            // determine the fixed nodes that should be duplicated (currently: all nodes up until the first control
+            // split, end node, deopt or return.
+            ArrayList<FixedNode> fixedNodes = new ArrayList<>();
+            FixedNode fixed = merge.next();
+            FrameState stateAfter = merge.stateAfter();
+            while (fixed instanceof FixedWithNextNode) {
+                fixedNodes.add(fixed);
+                if (fixed instanceof StateSplit && ((StateSplit) fixed).stateAfter() != null) {
+                    stateAfter = ((StateSplit) fixed).stateAfter();
+                }
+                fixed = ((FixedWithNextNode) fixed).next();
+            }
+
+            EndNode endAfter = createNewMerge(fixed, stateAfter);
+            MergeNode mergeAfter = endAfter.merge();
+            fixedNodes.add(endAfter);
+            final HashSet<Node> duplicatedNodes = buildDuplicatedNodeSet(fixedNodes, stateAfter);
+            mergeAfter.clearEnds();
+            expandDuplicated(duplicatedNodes, mergeAfter);
+
+            List<EndNode> endSnapshot = merge.forwardEnds().snapshot();
+            List<PhiNode> phiSnapshot = merge.phis().snapshot();
+
+            int endIndex = 0;
+            for (final EndNode forwardEnd : merge.forwardEnds()) {
+                Map<Node, Node> duplicates;
+                if (replacements == null || replacements.get(endIndex) == null) {
+                    duplicates = graph.addDuplicates(duplicatedNodes, (DuplicationReplacement) null);
+                } else {
+                    HashMap<Node, Node> replace = new HashMap<>();
+                    replace.put(replacements.get(endIndex).object(), replacements.get(endIndex));
+                    duplicates = graph.addDuplicates(duplicatedNodes, replace);
+                }
+                for (Map.Entry<ValueNode, PhiNode> phi : bottomPhis.entrySet()) {
+                    phi.getValue().initializeValueAt(merge.forwardEndIndex(forwardEnd), (ValueNode) duplicates.get(phi.getKey()));
+                }
+                mergeAfter.addForwardEnd((EndNode) duplicates.get(endAfter));
+
+                // re-wire the duplicated ValueAnchorNode to the predecessor of the corresponding EndNode
+                FixedNode anchorDuplicate = (FixedNode) duplicates.get(anchor);
+                ((FixedWithNextNode) forwardEnd.predecessor()).setNext(anchorDuplicate);
+                // move dependencies on the ValueAnchorNode to the previous BeginNode
+                BeginNode prevBegin = BeginNode.prevBegin(anchorDuplicate);
+                anchorDuplicate.replaceAtUsages(prevBegin);
+
+                // re-wire the phi duplicates to the correct input
+                for (PhiNode phi : phiSnapshot) {
+                    PhiNode phiDuplicate = (PhiNode) duplicates.get(phi);
+                    for (Node usage : phiDuplicate.usages()) {
+                        if (usage instanceof ValueNode) {
+                            ((ValueNode) usage).dependencies().add(prevBegin);
+                        }
+                    }
+                    phiDuplicate.replaceAtUsages(phi.valueAt(forwardEnd));
+                    phiDuplicate.safeDelete();
+                }
+                endIndex++;
+            }
+            GraphUtil.killCFG(merge);
+            for (EndNode forwardEnd : endSnapshot) {
+                forwardEnd.safeDelete();
+            }
+            for (PhiNode phi : phiSnapshot) {
+                // these phis should go away, but they still need to be anchored to a merge to be valid...
+                if (phi.isAlive()) {
+                    phi.setMerge(mergeAfter);
+                }
+            }
+            Debug.dump(graph, "After tail duplication at %s", merge);
+        }
+
+        /**
+         * Inserts a new ValueAnchorNode after the merge and transfers all dependency-usages (not phis) to this
+         * ValueAnchorNode.
+         *
+         * @return The new {@link ValueAnchorNode} that was created.
+         */
+        private ValueAnchorNode addValueAnchor() {
+            ValueAnchorNode anchor = graph.add(new ValueAnchorNode());
+            graph.addAfterFixed(merge, anchor);
+            for (Node usage : merge.usages().snapshot()) {
+                if (usage instanceof PhiNode && ((PhiNode) usage).merge() == merge) {
+                    // nothing to do
+                } else {
+                    usage.replaceFirstInput(merge, anchor);
+                }
+            }
+            return anchor;
+        }
+
+        /**
+         * Given a set of fixed nodes, this method determines the set of fixed and floating nodes that needs to be
+         * duplicated, i.e., all nodes that due to data flow and other dependencies needs to be duplicated.
+         *
+         * @param fixedNodes The set of fixed nodes that should be duplicated.
+         * @param stateAfter The frame state of the merge that follows the set of fixed nodes. All {@link ValueNode}s
+         *            reachable from this state are considered to be reachable from within the duplicated set of nodes.
+         * @return The set of nodes that need to be duplicated.
+         */
+        private HashSet<Node> buildDuplicatedNodeSet(final ArrayList<FixedNode> fixedNodes, FrameState stateAfter) {
+            final NodeBitMap aboveBound = graph.createNodeBitMap();
+            final NodeBitMap belowBound = graph.createNodeBitMap();
+
+            final Deque<Node> worklist = new ArrayDeque<>();
+
+            // Build the set of nodes that have (transitive) usages within the duplicatedNodes.
+            // This is achieved by iterating all nodes that are reachable via inputs from the the fixed nodes.
+            aboveBound.markAll(fixedNodes);
+            worklist.addAll(fixedNodes);
+
+            // the phis at the original merge should always be duplicated
+            for (PhiNode phi : merge.phis()) {
+                aboveBound.mark(phi);
+                worklist.add(phi);
+            }
+
+            NodeClosure<Node> aboveClosure = new NodeClosure<Node>() {
+
+                @Override
+                public void apply(Node usage, Node node) {
+                    if (node instanceof PhiNode && !fixedNodes.contains(((PhiNode) node).merge())) {
+                        // stop iterating: phis belonging to outside merges are known to be outside.
+                    } else if (node instanceof FixedNode) {
+                        // stop iterating: fixed nodes within the given set are traversal roots anyway, and all other
+                        // fixed nodes are known to be outside.
+                    } else if (!aboveBound.isMarked(node)) {
+                        worklist.add(node);
+                        aboveBound.mark(node);
+                    }
+                }
+            };
+
+            if (stateAfter != null) {
+                stateAfter.applyToNonVirtual(aboveClosure);
+            }
+            while (!worklist.isEmpty()) {
+                Node current = worklist.remove();
+                for (Node input : current.inputs()) {
+                    aboveClosure.apply(current, input);
+                }
+            }
+
+            // Build the set of nodes that have (transitive) inputs within the duplicatedNodes.
+            // This is achieved by iterating all nodes that are reachable via usages from the fixed nodes.
+            belowBound.markAll(fixedNodes);
+            worklist.addAll(fixedNodes);
+
+            // the phis at the original merge should always be duplicated
+            for (PhiNode phi : merge.phis()) {
+                belowBound.mark(phi);
+                worklist.add(phi);
+            }
+
+            while (!worklist.isEmpty()) {
+                Node current = worklist.remove();
+                for (Node usage : current.usages()) {
+                    if (usage instanceof PhiNode && !fixedNodes.contains(((PhiNode) usage).merge())) {
+                        // stop iterating: phis belonging to outside merges are known to be outside.
+                    } else if (usage instanceof FixedNode) {
+                        // stop iterating: fixed nodes within the given set are traversal roots anyway, and all other
+                        // fixed nodes are known to be outside.
+                    } else if (!belowBound.isMarked(usage)) {
+                        worklist.add(usage);
+                        belowBound.mark(usage);
+                    }
+                }
+            }
+
+            // build the intersection
+            belowBound.intersect(aboveBound);
+            HashSet<Node> result = new HashSet<>();
+            for (Node node : belowBound) {
+                result.add(node);
+            }
+            return result;
+        }
+
+        /**
+         * Creates a new merge and end node construct at the end of the duplicated area. While it is useless in itself
+         * (merge with only one end) it simplifies the later duplication step.
+         *
+         * @param successor The successor of the duplicated set of nodes, i.e., the first node that should not be
+         *            duplicated.
+         * @param stateAfterMerge The frame state that should be used for the merge.
+         * @return The newly created end node.
+         */
+        private EndNode createNewMerge(FixedNode successor, FrameState stateAfterMerge) {
+            MergeNode newBottomMerge = graph.add(new MergeNode());
+            newBottomMerge.setProbability(successor.probability());
+            EndNode newBottomEnd = graph.add(new EndNode());
+            newBottomMerge.addForwardEnd(newBottomEnd);
+            newBottomMerge.setStateAfter(stateAfterMerge);
+            ((FixedWithNextNode) successor.predecessor()).setNext(newBottomEnd);
+            newBottomMerge.setNext(successor);
+            return newBottomEnd;
+        }
+
+        /**
+         * Expands the set of nodes to be duplicated by looking at a number of conditions:
+         * <ul>
+         * <li>{@link ValueNode}s that have usages on the outside need to be replaced with phis for the outside usages.</li>
+         * <li>Non-{@link ValueNode} nodes that have outside usages (frame states, virtual object states, ...) need to
+         * be cloned immediately for the outside usages.</li>
+         * <li>Nodes that have a {@link StampFactory#extension()} or {@link StampFactory#condition()} stamp need to be
+         * cloned immediately for the outside usages.</li>
+         * <li>Dependencies into the duplicated nodes will be replaced with dependencies on the merge.</li>
+         * <li>Outside non-{@link ValueNode}s with usages within the duplicated set of nodes need to also be duplicated.
+         * </li>
+         * <li>Outside {@link ValueNode}s with {@link StampFactory#extension()} or {@link StampFactory#condition()}
+         * stamps that have usages within the duplicated set of nodes need to also be duplicated.</li>
+         * </ul>
+         *
+         * @param duplicatedNodes The set of duplicated nodes that will be modified (expanded).
+         * @param newBottomMerge The merge that follows the duplicated set of nodes. It will be used for newly created
+         *            phis and to as a target for dependencies that pointed into the duplicated set of nodes.
+         */
+        private void expandDuplicated(HashSet<Node> duplicatedNodes, MergeNode newBottomMerge) {
+            Deque<Node> worklist = new ArrayDeque<>(duplicatedNodes);
+
+            while (!worklist.isEmpty()) {
+                Node duplicated = worklist.remove();
+                if (hasUsagesOutside(duplicated, duplicatedNodes)) {
+                    boolean cloneForOutsideUsages = false;
+                    if (duplicated instanceof ValueNode) {
+                        ValueNode node = (ValueNode) duplicated;
+                        if (node.stamp() == StampFactory.dependency()) {
+                            // re-route dependencies to the merge
+                            replaceUsagesOutside(node, newBottomMerge, duplicatedNodes);
+                            // TODO(ls) maybe introduce phis for dependencies
+                        } else if (node.stamp() == StampFactory.extension() || node.stamp() == StampFactory.condition()) {
+                            cloneForOutsideUsages = true;
+                        } else {
+                            // introduce a new phi
+                            PhiNode newPhi = bottomPhis.get(node);
+                            if (newPhi == null) {
+                                newPhi = graph.add(new PhiNode(node.kind(), newBottomMerge));
+                                bottomPhis.put(node, newPhi);
+                                newPhi.addInput(node);
+                            }
+                            replaceUsagesOutside(node, newPhi, duplicatedNodes);
+                        }
+                    } else {
+                        cloneForOutsideUsages = true;
+                    }
+                    if (cloneForOutsideUsages) {
+                        // clone the offending node to the outside
+                        Node newOutsideClone = duplicated.copyWithInputs();
+                        replaceUsagesOutside(duplicated, newOutsideClone, duplicatedNodes);
+                        // this might cause other nodes to have outside usages, we need to look at those as well
+                        for (Node input : newOutsideClone.inputs()) {
+                            if (duplicatedNodes.contains(input)) {
+                                worklist.add(input);
+                            }
+                        }
+                    }
+                }
+                // check if this node has an input that lies outside and cannot be shared
+                for (Node input : duplicated.inputs()) {
+                    if (!duplicatedNodes.contains(input)) {
+                        boolean duplicateInput = false;
+                        if (input instanceof VirtualState) {
+                            duplicateInput = true;
+                        } else if (input instanceof ValueNode) {
+                            Stamp inputStamp = ((ValueNode) input).stamp();
+                            if (inputStamp == StampFactory.extension() || inputStamp == StampFactory.condition()) {
+                                duplicateInput = true;
+                            }
+                        }
+                        if (duplicateInput) {
+                            duplicatedNodes.add(input);
+                            worklist.add(input);
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * Checks if the given node has usages that are not within the given set of nodes.
+         *
+         * @param node The node whose usages are checked.
+         * @param nodeSet The set of nodes that are considered to be "within".
+         * @return true if the given node has usages on the outside, false otherwise.
+         */
+        private static boolean hasUsagesOutside(Node node, HashSet<Node> nodeSet) {
+            for (Node usage : node.usages()) {
+                if (!nodeSet.contains(usage)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /**
+         * Replaces the given node with the given replacement at all usages that are not within the given set of nodes.
+         *
+         * @param node The node to be replaced at outside usages.
+         * @param replacement The node that replaced the given node at outside usages.
+         * @param nodeSet The set of nodes that are considered to be "within".
+         */
+        private static void replaceUsagesOutside(Node node, Node replacement, HashSet<Node> nodeSet) {
+            for (Node usage : node.usages().snapshot()) {
+                if (!nodeSet.contains(usage)) {
+                    usage.replaceFirstInput(node, replacement);
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Wed Jul 18 10:50:57 2012 -0700
@@ -72,11 +72,11 @@
         return new FrameMap(runtime, target, registerConfig);
     }
 
-    public abstract LIRGenerator newLIRGenerator(Graph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, RiXirGenerator xir, Assumptions assumptions);
+    public abstract LIRGenerator newLIRGenerator(Graph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, XirGenerator xir, Assumptions assumptions);
 
     public abstract TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir);
 
-    public abstract CiXirAssembler newXirAssembler();
+    public abstract XirAssembler newXirAssembler();
 
     /**
      * Emits code to do stack overflow checking.
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Wed Jul 18 10:50:57 2012 -0700
@@ -29,13 +29,7 @@
 
 import java.util.*;
 
-import com.oracle.max.asm.*;
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
-import com.oracle.max.cri.xir.*;
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CompilationResult.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
@@ -44,7 +38,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.JumpOp;
 import com.oracle.graal.lir.StandardOp.LabelOp;
-import com.oracle.graal.lir.LIRValueUtil;
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.DivOp;
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op1Reg;
 import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op1Stack;
@@ -54,7 +47,14 @@
 import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
 import com.oracle.graal.lir.amd64.AMD64Call.IndirectCallOp;
 import com.oracle.graal.lir.amd64.AMD64Compare.CompareOp;
-import com.oracle.graal.lir.amd64.AMD64ControlFlow.*;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.FloatBranchOp;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.FloatCondMoveOp;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.ReturnOp;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.SequentialSwitchOp;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.SwitchRangesOp;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.TableSwitchOp;
 import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LeaOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
@@ -64,10 +64,15 @@
 import com.oracle.graal.lir.amd64.AMD64Move.NullCheckOp;
 import com.oracle.graal.lir.amd64.AMD64Move.SpillMoveOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreOp;
+import com.oracle.graal.lir.asm.TargetMethodAssembler.CallPositionListener;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
+import com.oracle.max.cri.xir.*;
 
 /**
  * This class implements the X86-specific portion of the LIR generator.
@@ -93,7 +98,7 @@
         }
     }
 
-    public AMD64LIRGenerator(Graph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, RiXirGenerator xir, Assumptions assumptions) {
+    public AMD64LIRGenerator(Graph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, XirGenerator xir, Assumptions assumptions) {
         super(graph, runtime, target, frameMap, method, lir, xir, assumptions);
         lir.spillMoveFactory = new AMD64SpillMoveFactory();
     }
@@ -542,11 +547,11 @@
     }
 
     @Override
-    protected void emitCall(Object targetMethod, Value result, List<Value> arguments, Value targetAddress, LIRFrameState info, Map<XirMark, Mark> marks) {
+    protected void emitCall(Object targetMethod, Value result, List<Value> arguments, Value targetAddress, LIRFrameState info, CallPositionListener cpl) {
         if (isConstant(targetAddress)) {
-            append(new DirectCallOp(targetMethod, result, arguments.toArray(new Value[arguments.size()]), info, marks));
+            append(new DirectCallOp(targetMethod, result, arguments.toArray(new Value[arguments.size()]), info, cpl));
         } else {
-            append(new IndirectCallOp(targetMethod, result, arguments.toArray(new Value[arguments.size()]), targetAddress, info, marks));
+            append(new IndirectCallOp(targetMethod, result, arguments.toArray(new Value[arguments.size()]), targetAddress, info, cpl));
         }
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirAssembler.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirAssembler.java	Wed Jul 18 10:50:57 2012 -0700
@@ -32,10 +32,10 @@
 import com.oracle.max.cri.xir.*;
 
 /**
- * AMD64 version of {@link CiXirAssembler}.
+ * AMD64 version of {@link XirAssembler}.
  *
  */
-public class AMD64XirAssembler extends CiXirAssembler {
+public class AMD64XirAssembler extends XirAssembler {
     public AMD64XirAssembler(TargetDescription target) {
         super(target);
     }
@@ -216,7 +216,7 @@
     }
 
     @Override
-    public CiXirAssembler copy() {
+    public XirAssembler copy() {
         return new AMD64XirAssembler(target);
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java	Wed Jul 18 10:50:57 2012 -0700
@@ -39,10 +39,10 @@
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.max.cri.xir.*;
-import com.oracle.max.cri.xir.CiXirAssembler.RuntimeCallInformation;
-import com.oracle.max.cri.xir.CiXirAssembler.XirInstruction;
-import com.oracle.max.cri.xir.CiXirAssembler.XirLabel;
-import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
+import com.oracle.max.cri.xir.XirAssembler.RuntimeCallInformation;
+import com.oracle.max.cri.xir.XirAssembler.XirInstruction;
+import com.oracle.max.cri.xir.XirAssembler.XirLabel;
+import com.oracle.max.cri.xir.XirAssembler.XirMark;
 
 public class AMD64XirOp extends LIRXirInstruction {
     public AMD64XirOp(XirSnippet snippet, Value[] operands, Value outputOperand, Value[] inputs, Value[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex,
@@ -179,7 +179,7 @@
                 }
 
                 case PointerLoadDisp: {
-                    CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra;
+                    XirAssembler.AddressAccessInformation addressInformation = (XirAssembler.AddressAccessInformation) inst.extra;
                     boolean canTrap = addressInformation.canTrap;
 
                     Address.Scale scale = addressInformation.scale;
@@ -206,7 +206,7 @@
                 }
 
                 case LoadEffectiveAddress: {
-                    CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra;
+                    XirAssembler.AddressAccessInformation addressInformation = (XirAssembler.AddressAccessInformation) inst.extra;
 
                     Address.Scale scale = addressInformation.scale;
                     int displacement = addressInformation.disp;
@@ -223,7 +223,7 @@
                 }
 
                 case PointerStoreDisp: {
-                    CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra;
+                    XirAssembler.AddressAccessInformation addressInformation = (XirAssembler.AddressAccessInformation) inst.extra;
                     boolean canTrap = addressInformation.canTrap;
 
                     Address.Scale scale = addressInformation.scale;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Wed Jul 18 10:50:57 2012 -0700
@@ -28,13 +28,13 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.JavaTypeProfile.*;
+import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.FrameState.*;
+import com.oracle.graal.nodes.FrameState.InliningIdentifier;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
@@ -45,6 +45,8 @@
 
 public class InliningUtil {
 
+    private static final DebugMetric metricInliningTailDuplication = Debug.metric("InliningTailDuplication");
+
     public interface InliningCallback {
         StructuredGraph buildGraph(ResolvedJavaMethod method);
         double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke);
@@ -270,6 +272,7 @@
         private void inlineMultipleMethods(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, int numberOfMethods, boolean hasReturnValue) {
             FixedNode continuation = invoke.next();
 
+            ValueNode originalReceiver = invoke.callTarget().receiver();
             // setup merge and phi nodes for results and exceptions
             MergeNode returnMerge = graph.add(new MergeNode());
             returnMerge.setProbability(invoke.probability());
@@ -329,7 +332,7 @@
                 GraphUtil.killCFG(invokeWithExceptionNode.exceptionEdge());
             }
 
-            // replace the invoke with a cascade of if nodes
+            // replace the invoke with a switch on the type of the actual receiver
             ReadHubNode objectClassNode = graph.add(new ReadHubNode(invoke.callTarget().receiver()));
             graph.addBeforeFixed(invoke.node(), objectClassNode);
             FixedNode dispatchOnType = createDispatchOnType(graph, objectClassNode, calleeEntryNodes, unknownTypeNode);
@@ -340,6 +343,8 @@
             invoke.node().replaceAtUsages(returnValuePhi);
             invoke.node().replaceAndDelete(dispatchOnType);
 
+            ArrayList<PiNode> replacements = new ArrayList<>();
+
             // do the actual inlining for every invoke
             for (int i = 0; i < calleeEntryNodes.length; i++) {
                 BeginNode node = calleeEntryNodes[i];
@@ -347,7 +352,7 @@
 
                 ResolvedJavaType commonType = getLeastCommonType(i);
                 ValueNode receiver = invokeForInlining.callTarget().receiver();
-                ValueNode anchoredReceiver = createAnchoredReceiver(graph, node, commonType, receiver);
+                PiNode anchoredReceiver = createAnchoredReceiver(graph, node, commonType, receiver);
                 invokeForInlining.callTarget().replaceFirstInput(receiver, anchoredReceiver);
 
                 ResolvedJavaMethod concrete = concretes.get(i);
@@ -355,6 +360,31 @@
                 callback.recordMethodContentsAssumption(concrete);
                 assert !IntrinsificationPhase.canIntrinsify(invokeForInlining, concrete, runtime);
                 InliningUtil.inline(invokeForInlining, calleeGraph, false);
+                replacements.add(anchoredReceiver);
+            }
+            if (shouldFallbackToInvoke()) {
+                replacements.add(null);
+            }
+            if (GraalOptions.OptTailDuplication) {
+                /*
+                 * We might want to perform tail duplication at the merge after a type switch, if there are invokes that would
+                 * benefit from the improvement in type information.
+                 */
+                FixedNode current = returnMerge;
+                int opportunities = 0;
+                do {
+                    if (current instanceof InvokeNode && ((InvokeNode) current).callTarget().receiver() == originalReceiver) {
+                        opportunities++;
+                    } else if (current.inputs().contains(originalReceiver)) {
+                        opportunities++;
+                    }
+                    current = ((FixedWithNextNode) current).next();
+                } while (current instanceof FixedWithNextNode);
+                if (opportunities > 0) {
+                    metricInliningTailDuplication.increment();
+                    Debug.log("MultiTypeGuardInlineInfo starting tail duplication (%d opportunities)", opportunities);
+                    TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacements);
+                }
             }
         }
 
@@ -679,7 +709,7 @@
         }
     }
 
-    private static ValueNode createAnchoredReceiver(StructuredGraph graph, FixedNode anchor, ResolvedJavaType commonType, ValueNode receiver) {
+    private static PiNode createAnchoredReceiver(StructuredGraph graph, FixedNode anchor, ResolvedJavaType commonType, ValueNode receiver) {
         // to avoid that floating reads on receiver fields float above the type check
         return graph.unique(new PiNode(receiver, anchor, StampFactory.declaredNonNull(commonType)));
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/Util.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/Util.java	Wed Jul 18 10:50:57 2012 -0700
@@ -336,4 +336,23 @@
     public static boolean isFloating(Node n) {
         return n instanceof FloatingNode;
     }
+
+    /**
+     * Creates an array of integers of length "size", in which each number from 0 to (size - 1) occurs exactly once. The
+     * integers are sorted using the given comparator. This can be used to create a sorting for arrays that cannot be
+     * modified directly.
+     *
+     * @param size The size of the range to be sorted.
+     * @param comparator A comparator that is used to compare indexes.
+     * @return An array of integers that contains each number from 0 to (size - 1) exactly once, sorted using the
+     *         comparator.
+     */
+    public static Integer[] createSortedPermutation(int size, Comparator<Integer> comparator) {
+        Integer[] indexes = new Integer[size];
+        for (int i = 0; i < size; i++) {
+            indexes[i] = i;
+        }
+        Arrays.sort(indexes, comparator);
+        return indexes;
+    }
 }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugDumpHandler.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugDumpHandler.java	Wed Jul 18 10:50:57 2012 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.debug;
 
-public interface DebugDumpHandler {
+import java.io.*;
+
+public interface DebugDumpHandler extends Closeable {
     void dump(Object object, String message);
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Wed Jul 18 10:50:57 2012 -0700
@@ -47,7 +47,6 @@
     private int deletedNodeCount;
     private GraphEventLog eventLog;
 
-    ArrayList<Node> usagesDropped = new ArrayList<>();
     InputChangedListener inputChanged;
     private final HashMap<CacheEntry, Node> cachedNodes = new HashMap<>();
 
@@ -149,16 +148,6 @@
         return node;
     }
 
-    public int getUsagesDroppedNodesCount() {
-        return usagesDropped.size();
-    }
-
-    public List<Node> getAndCleanUsagesDroppedNodes() {
-        ArrayList<Node> result = usagesDropped;
-        usagesDropped = new ArrayList<>();
-        return result;
-    }
-
     public interface InputChangedListener {
         void inputChanged(Node node);
     }
@@ -322,6 +311,11 @@
                 }
                 return super.filter(clazz);
             }
+
+            @Override
+            public int count() {
+                return getNodeCount();
+            }
         };
     }
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Wed Jul 18 10:50:57 2012 -0700
@@ -50,6 +50,11 @@
     static final int INITIAL_ID = -1;
     static final int ALIVE_ID_START = 0;
 
+    /**
+     * Denotes a node input. This should be applied to exactly the fields of a node that are of type {@link Node}.
+     * Nodes that update their inputs outside of their constructor should call {@link Node#updateUsages(Node, Node)}
+     * just prior to doing the update of the input.
+     */
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.FIELD)
     public static @interface Input {
@@ -279,9 +284,6 @@
 
     private boolean removeThisFromUsages(Node n) {
         if (n.usages.remove(this)) {
-            if (n.usages.size() == 0) {
-                graph.usagesDropped.add(n);
-            }
             return true;
         } else {
             return false;
@@ -419,12 +421,19 @@
 
     /**
      * Provides a {@link Map} of properties of this node for use in debugging (e.g., to view in the ideal graph
-     * visualizer). Subclasses overriding this method should add to the map returned by their superclass.
+     * visualizer).
      */
     public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> map = new HashMap<>();
-        map.put("usageCount", usages.size());
-        map.put("predecessorCount", predecessor == null ? 0 : 1);
+        return getDebugProperties(new HashMap<>());
+    }
+
+
+    /**
+     * Fills a {@link Map} with properties of this node for use in debugging (e.g., to view in the ideal graph
+     * visualizer). Subclasses overriding this method should also fill the map using their superclass.
+     * @param map
+     */
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
         getNodeClass().getDebugProperties(this, map);
         return map;
     }
@@ -492,6 +501,12 @@
         }
     }
 
+
+    @Deprecated
+    public int getId() {
+        return id;
+    }
+
     @Override
     public void formatTo(Formatter formatter, int flags, int width, int precision) {
         if ((flags & FormattableFlags.ALTERNATE) == FormattableFlags.ALTERNATE) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Wed Jul 18 10:50:57 2012 -0700
@@ -26,9 +26,7 @@
 
 import com.oracle.graal.graph.iterators.*;
 
-
-
-public final class NodeBitMap extends AbstractNodeIterable<Node>{
+public final class NodeBitMap extends AbstractNodeIterable<Node> {
     private final boolean autoGrow;
     private final BitSet bitMap;
     private final Graph graph;
@@ -98,6 +96,11 @@
         bitMap.clear();
     }
 
+    public void intersect(NodeBitMap other) {
+        assert graph == other.graph;
+        bitMap.and(other.bitMap);
+    }
+
     public void grow(Node node) {
         nodeCount = Math.max(nodeCount, node.id() + 1);
     }
@@ -120,6 +123,7 @@
     }
 
     private static class MarkedNodeIterator implements Iterator<Node> {
+
         private final NodeBitMap visited;
         private Iterator<Node> nodes;
         private Node nextNode;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Wed Jul 18 10:50:57 2012 -0700
@@ -28,6 +28,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
+import com.oracle.graal.graph.Node.*;
 
 import sun.misc.Unsafe;
 
@@ -83,6 +84,7 @@
     private final boolean canGVN;
     private final int startGVNNumber;
     private final String shortName;
+    private final String nameTemplate;
     private final int iterableId;
     private final boolean hasOutgoingEdges;
 
@@ -122,12 +124,17 @@
         if (newShortName.endsWith("Node") && !newShortName.equals("StartNode") && !newShortName.equals("EndNode")) {
             newShortName = newShortName.substring(0, newShortName.length() - 4);
         }
+        String newNameTemplate = null;
         NodeInfo info = clazz.getAnnotation(NodeInfo.class);
         if (info != null) {
             if (!info.shortName().isEmpty()) {
                 newShortName = info.shortName();
             }
+            if (!info.nameTemplate().isEmpty()) {
+                newNameTemplate = info.nameTemplate();
+            }
         }
+        this.nameTemplate = newNameTemplate == null ? newShortName : newNameTemplate;
         this.shortName = newShortName;
         if (Node.IterableNodeType.class.isAssignableFrom(clazz)) {
             this.iterableId = nextIterableId++;
@@ -572,17 +579,8 @@
                 }
             } else {
                 value = unsafe.getObject(node, dataOffsets[i]);
-                if (type.isArray()) {
-                    if (!type.getComponentType().isPrimitive()) {
-                        value = Arrays.toString((Object[]) value);
-                    } else if (type.getComponentType() == Integer.TYPE) {
-                        value = Arrays.toString((int[]) value);
-                    } else if (type.getComponentType() == Double.TYPE) {
-                        value = Arrays.toString((double[]) value);
-                    }
-                }
             }
-            properties.put("data." + dataNames[i], value);
+            properties.put(dataNames[i], value);
         }
     }
 
@@ -909,12 +907,32 @@
         return false;
     }
 
-    public int directInputCount() {
-        return directInputCount;
+    public List<Position> getFirstLevelInputPositions() {
+        List<Position> positions = new ArrayList<>(inputOffsets.length);
+        for (int i = 0; i < inputOffsets.length; i++) {
+            positions.add(new Position(true, i, NOT_ITERABLE));
+        }
+        return positions;
     }
 
-    public int directSuccessorCount() {
-        return directSuccessorCount;
+    public List<Position> getFirstLevelSuccessorPositions() {
+        List<Position> positions = new ArrayList<>(successorOffsets.length);
+        for (int i = 0; i < successorOffsets.length; i++) {
+            positions.add(new Position(false, i, NOT_ITERABLE));
+        }
+        return positions;
+    }
+
+    public Class<?> getJavaClass() {
+        return clazz;
+    }
+
+    /**
+     * The template used to build the {@link Verbosity#Name} version.
+     * Variable part are specified using &#123;i#inputName&#125; or &#123;p#propertyName&#125;.
+     */
+    public String getNameTemplate() {
+        return nameTemplate;
     }
 
     static Map<Node, Node> addGraphDuplicate(Graph graph, Iterable<Node> nodes, DuplicationReplacement replacements) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInfo.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInfo.java	Wed Jul 18 10:50:57 2012 -0700
@@ -27,9 +27,16 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
+import com.oracle.graal.graph.Node.*;
+
 
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.TYPE)
 public @interface NodeInfo {
     String shortName() default "";
+    /**
+     * The template used to build the {@link Verbosity#Name} version.
+     * Variable part are specified using &#123;i#inputName&#125; or &#123;p#propertyName&#125;.
+     */
+    String nameTemplate() default "";
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Wed Jul 18 10:50:57 2012 -0700
@@ -55,7 +55,7 @@
             this.nodes = new Node[elements.length];
             for (int i = 0; i < elements.length; i++) {
                 this.nodes[i] = elements[i];
-                assert this.nodes[i] == null || !this.nodes[i].isDeleted();
+                assert this.nodes[i] == null || !this.nodes[i].isDeleted() : "Initializing nodelist with deleted element : " + nodes[i];
             }
         }
     }
@@ -254,6 +254,13 @@
         return (List<T>) Arrays.asList(Arrays.copyOf(this.nodes, this.size));
     }
 
+    @Override
+    public void snapshotTo(List<T> to) {
+        for (int i = 0; i < size; i++) {
+            to.add(get(i));
+        }
+    }
+
     @SuppressWarnings("unchecked")
     public void setAll(NodeList<T> values) {
         incModCount();
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/AbstractNodeIterable.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/AbstractNodeIterable.java	Wed Jul 18 10:50:57 2012 -0700
@@ -65,6 +65,12 @@
         return list;
     }
     @Override
+    public void snapshotTo(List<T> to) {
+        for (T n : this) {
+            to.add(n);
+        }
+    }
+    @Override
     public T first() {
         Iterator<T> iterator = iterator();
         if (iterator.hasNext()) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java	Wed Jul 18 10:50:57 2012 -0700
@@ -44,6 +44,8 @@
 
     List<T> snapshot();
 
+    void snapshotTo(List<T> to);
+
     T first();
 
     int count();
--- a/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/ReplacingStreams.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/ReplacingStreams.java	Wed Jul 18 10:50:57 2012 -0700
@@ -27,7 +27,6 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.logging.*;
 
 public class ReplacingStreams {
@@ -48,7 +47,6 @@
         invocation = new InvocationSocket(output, input);
 
         addStaticObject(Value.IllegalValue);
-        addStaticObject(HotSpotProxy.DUMMY_CONSTANT_OBJ);
     }
 
     public void setInvocationSocket(InvocationSocket invocation) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Wed Jul 18 10:50:57 2012 -0700
@@ -47,19 +47,19 @@
 
     private volatile boolean cancelled;
 
-    private final HotSpotGraalRuntime compiler;
+    private final HotSpotGraalRuntime graalRuntime;
     private final PhasePlan plan;
     private final HotSpotResolvedJavaMethod method;
     private final OptimisticOptimizations optimisticOpts;
     private final int id;
     private final int priority;
 
-    public static CompilationTask create(HotSpotGraalRuntime compiler, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int id, int priority) {
-        return new CompilationTask(compiler, plan, optimisticOpts, method, id, priority);
+    public static CompilationTask create(HotSpotGraalRuntime graalRuntime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int id, int priority) {
+        return new CompilationTask(graalRuntime, plan, optimisticOpts, method, id, priority);
     }
 
-    private CompilationTask(HotSpotGraalRuntime compiler, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int id, int priority) {
-        this.compiler = compiler;
+    private CompilationTask(HotSpotGraalRuntime graalRuntime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int id, int priority) {
+        this.graalRuntime = graalRuntime;
         this.plan = plan;
         this.method = method;
         this.optimisticOpts = optimisticOpts;
@@ -115,9 +115,9 @@
 
                     @Override
                     public CompilationResult call() throws Exception {
-                        compiler.evictDeoptedGraphs();
+                        graalRuntime.evictDeoptedGraphs();
                         StructuredGraph graph = new StructuredGraph(method);
-                        return compiler.getCompiler().compileMethod(method, graph, -1, compiler.getCache(), plan, optimisticOpts);
+                        return graalRuntime.getCompiler().compileMethod(method, graph, -1, graalRuntime.getCache(), plan, optimisticOpts);
                     }
                 });
             } finally {
@@ -148,11 +148,11 @@
     }
 
     private void installMethod(final CompilationResult tm) {
-        Debug.scope("CodeInstall", new Object[] {new DebugDumpScope(String.valueOf(id), true), compiler.getCompiler(), method}, new Runnable() {
+        Debug.scope("CodeInstall", new Object[] {new DebugDumpScope(String.valueOf(id), true), graalRuntime.getCompiler(), method}, new Runnable() {
             @Override
             public void run() {
                 final CodeInfo[] info = Debug.isDumpEnabled() ? new CodeInfo[1] : null;
-                compiler.getRuntime().installMethod(method, tm, info);
+                graalRuntime.getRuntime().installMethod(method, tm, info);
                 if (info != null) {
                     Debug.dump(new Object[] {tm, info[0]}, "After code installation");
                 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Wed Jul 18 10:50:57 2012 -0700
@@ -56,12 +56,25 @@
 
     @Override
     public void run() {
+        HotSpotDebugConfig hotspotDebugConfig = null;
         if (GraalOptions.Debug) {
             Debug.enable();
             PrintStream log = HotSpotGraalRuntime.getInstance().getVMToCompiler().log();
-            HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, log);
+            hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, log);
             Debug.setConfig(hotspotDebugConfig);
         }
-        super.run();
+        try {
+            super.run();
+        } finally {
+            if (hotspotDebugConfig != null) {
+                for (DebugDumpHandler dumpHandler : hotspotDebugConfig.dumpHandlers()) {
+                    try {
+                        dumpHandler.close();
+                    } catch (Throwable t) {
+
+                    }
+                }
+            }
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,87 @@
+/*
+ * 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.hotspot;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CompilationResult.*;
+import com.oracle.graal.hotspot.logging.*;
+import com.oracle.graal.hotspot.meta.*;
+
+/**
+ * Augments a {@link CompilationResult} with HotSpot-specific information.
+ */
+public final class HotSpotCompilationResult extends CompilerObject {
+
+    private static final long serialVersionUID = 7807321392203253218L;
+    public final CompilationResult comp;
+    public final HotSpotResolvedJavaMethod method; // used only for methods
+    public final String name; // used only for stubs
+
+    public final Site[] sites;
+    public final ExceptionHandler[] exceptionHandlers;
+
+    public HotSpotCompilationResult(HotSpotResolvedJavaMethod method, CompilationResult comp) {
+        this.method = method;
+        this.comp = comp;
+        this.name = null;
+
+        sites = getSortedSites(comp);
+        if (comp.getExceptionHandlers() == null) {
+            exceptionHandlers = null;
+        } else {
+            exceptionHandlers = comp.getExceptionHandlers().toArray(new ExceptionHandler[comp.getExceptionHandlers().size()]);
+        }
+    }
+
+    private static Site[] getSortedSites(CompilationResult target) {
+        List<?>[] lists = new List<?>[] {target.getSafepoints(), target.getDataReferences(), target.getMarks()};
+        int count = 0;
+        for (List<?> list : lists) {
+            count += list.size();
+        }
+        Site[] result = new Site[count];
+        int pos = 0;
+        for (List<?> list : lists) {
+            for (Object elem : list) {
+                result[pos++] = (Site) elem;
+            }
+        }
+        Arrays.sort(result, new Comparator<Site>() {
+
+            public int compare(Site s1, Site s2) {
+                if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) {
+                    return s1 instanceof Mark ? -1 : 1;
+                }
+                return s1.pcOffset - s2.pcOffset;
+            }
+        });
+        if (Logger.ENABLED) {
+            for (Site site : result) {
+                Logger.log(site.pcOffset + ": " + site);
+            }
+        }
+        return result;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java	Wed Jul 18 10:50:57 2012 -0700
@@ -64,13 +64,10 @@
         if (logFilter != null || meterFilter != null || timerFilter != null || dumpFilter != null || methodFilter != null) {
             TTY.println(Thread.currentThread().getName() + ": " + toString());
         }
-
-        if (GraalOptions.PrintIdealGraphFile) {
-            dumpHandlers.add(new IdealGraphPrinterDumpHandler());
-        } else {
-            dumpHandlers.add(new IdealGraphPrinterDumpHandler(GraalOptions.PrintIdealGraphAddress, GraalOptions.PrintIdealGraphPort));
+        dumpHandlers.add(new GraphPrinterDumpHandler());
+        if (GraalOptions.PrintCFG) {
+            dumpHandlers.add(new CFGPrinterObserver());
         }
-        dumpHandlers.add(new CFGPrinterObserver());
         this.output = output;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Wed Jul 18 10:50:57 2012 -0700
@@ -32,6 +32,7 @@
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.target.amd64.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.cri.xir.*;
@@ -116,9 +117,9 @@
             // these options are important - graal will not generate correct code without them
             GraalOptions.StackShadowPages = config.stackShadowPages;
 
-            RiXirGenerator generator = new HotSpotXirGenerator(config, getTarget(), getRuntime().getGlobalStubRegisterConfig(), this);
+            XirGenerator generator = new HotSpotXirGenerator(config, getTarget(), getRuntime().getGlobalStubRegisterConfig(), this);
             if (Logger.ENABLED) {
-                generator = LoggingProxy.getProxy(RiXirGenerator.class, generator);
+                generator = LoggingProxy.getProxy(XirGenerator.class, generator);
             }
 
             Backend backend = Backend.create(runtime, target);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotProxy.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * 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.hotspot;
-
-/**
- * Provides methods to classify the HotSpot-internal identifiers.
- */
-public final class HotSpotProxy {
-
-    private HotSpotProxy() {
-    }
-
-    private enum CompilerObjectType {
-        // this enum needs to have the same values as the one in graal_Compiler.hpp
-        STUB(0x100000000000000L),
-        METHOD(0x200000000000000L),
-        CLASS(0x300000000000000L),
-        SYMBOL(0x400000000000000L),
-        CONSTANT_POOL(0x500000000000000L),
-        CONSTANT(0x600000000000000L),
-        TYPE_MASK(0xf00000000000000L),
-        DUMMY_CONSTANT(0x6ffffffffffffffL);
-
-        public final long bits;
-
-        CompilerObjectType(long bits) {
-            this.bits = bits;
-        }
-    }
-
-    public static final Long DUMMY_CONSTANT_OBJ = CompilerObjectType.DUMMY_CONSTANT.bits;
-
-    private static boolean isType(long id, CompilerObjectType type) {
-        return (id & CompilerObjectType.TYPE_MASK.bits) == type.bits;
-    }
-
-    public static boolean isStub(long id) {
-        return isType(id, CompilerObjectType.STUB);
-    }
-
-    public static boolean isMethod(long id) {
-        return isType(id, CompilerObjectType.METHOD);
-    }
-
-    public static boolean isClass(long id) {
-        return isType(id, CompilerObjectType.CLASS);
-    }
-
-    public static boolean isSymbol(long id) {
-        return isType(id, CompilerObjectType.SYMBOL);
-    }
-
-    public static boolean isConstantPool(long id) {
-        return isType(id, CompilerObjectType.CONSTANT_POOL);
-    }
-
-    public static boolean isConstant(long id) {
-        return isType(id, CompilerObjectType.CONSTANT_POOL);
-    }
-
-    public static String toString(long id) {
-        CompilerObjectType type = null;
-        for (CompilerObjectType t : CompilerObjectType.values()) {
-            if ((id & CompilerObjectType.TYPE_MASK.bits) == t.bits) {
-                type = t;
-            }
-        }
-        long num = id & ~CompilerObjectType.TYPE_MASK.bits;
-        return type + " " + num;
-    }
-
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetMethod.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * 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.hotspot;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CompilationResult.*;
-import com.oracle.graal.hotspot.logging.*;
-import com.oracle.graal.hotspot.meta.*;
-
-/**
- * CiTargetMethod augmented with HotSpot-specific information.
- */
-public final class HotSpotTargetMethod extends CompilerObject {
-
-    private static final long serialVersionUID = 7807321392203253218L;
-    public final CompilationResult targetMethod;
-    public final HotSpotResolvedJavaMethod method; // used only for methods
-    public final String name; // used only for stubs
-
-    public final Site[] sites;
-    public final ExceptionHandler[] exceptionHandlers;
-
-    public HotSpotTargetMethod(HotSpotResolvedJavaMethod method, CompilationResult targetMethod) {
-        this.method = method;
-        this.targetMethod = targetMethod;
-        this.name = null;
-
-        sites = getSortedSites(targetMethod);
-        if (targetMethod.getExceptionHandlers() == null) {
-            exceptionHandlers = null;
-        } else {
-            exceptionHandlers = targetMethod.getExceptionHandlers().toArray(new ExceptionHandler[targetMethod.getExceptionHandlers().size()]);
-        }
-    }
-
-    private static Site[] getSortedSites(CompilationResult target) {
-        List<?>[] lists = new List<?>[] {target.getSafepoints(), target.getDataReferences(), target.getMarks()};
-        int count = 0;
-        for (List<?> list : lists) {
-            count += list.size();
-        }
-        Site[] result = new Site[count];
-        int pos = 0;
-        for (List<?> list : lists) {
-            for (Object elem : list) {
-                result[pos++] = (Site) elem;
-            }
-        }
-        Arrays.sort(result, new Comparator<Site>() {
-
-            public int compare(Site s1, Site s2) {
-                if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) {
-                    return s1 instanceof Mark ? -1 : 1;
-                }
-                return s1.pcOffset - s2.pcOffset;
-            }
-        });
-        if (Logger.ENABLED) {
-            for (Site site : result) {
-                Logger.log(site.pcOffset + ": " + site);
-            }
-        }
-        return result;
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Jul 18 10:50:57 2012 -0700
@@ -138,9 +138,6 @@
     public long newTypeArrayStub;
     public long newObjectArrayStub;
     public long newMultiArrayStub;
-    public long loadKlassStub;
-    public long accessFieldStub;
-    public long resolveStaticCallStub;
     public long inlineCacheMissStub;
     public long handleExceptionStub;
     public long handleDeoptStub;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/MethodFilter.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/MethodFilter.java	Wed Jul 18 10:50:57 2012 -0700
@@ -107,7 +107,7 @@
     }
 
     public boolean matches(JavaMethod o) {
-        // check method name first, since CiUtil.toJavaName is expensive
+        // check method name first, since MetaUtil.toJavaName is expensive
         if (methodName != null && !methodName.matcher(o.name()).matches()) {
             return false;
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Jul 18 10:50:57 2012 -0700
@@ -63,7 +63,7 @@
 
     void ConstantPool_loadReferencedType(HotSpotResolvedJavaType pool, int cpi, byte byteCode);
 
-    HotSpotCompiledMethod installMethod(HotSpotTargetMethod targetMethod, boolean makeDefault, HotSpotCodeInfo info);
+    HotSpotCompiledMethod installMethod(HotSpotCompilationResult compResult, boolean makeDefault, HotSpotCodeInfo info);
 
     HotSpotVMConfig getConfiguration();
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Jul 18 10:50:57 2012 -0700
@@ -77,7 +77,7 @@
     public native JavaField ConstantPool_lookupField(HotSpotResolvedJavaType pool, int cpi, byte byteCode);
 
     @Override
-    public native HotSpotCompiledMethod installMethod(HotSpotTargetMethod targetMethod, boolean makeDefault, HotSpotCodeInfo info);
+    public native HotSpotCompiledMethod installMethod(HotSpotCompilationResult comp, boolean makeDefault, HotSpotCodeInfo info);
 
     @Override
     public native HotSpotVMConfig getConfiguration();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Jul 18 10:50:57 2012 -0700
@@ -39,6 +39,7 @@
 import com.oracle.graal.hotspot.counters.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.snippets.*;
+import com.oracle.graal.hotspot.target.amd64.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.max.criutils.*;
@@ -113,7 +114,7 @@
                 @Override
                 public void run() {
                     VMToCompilerImpl.this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime);
-                    SnippetInstaller installer = new SnippetInstaller(runtime, runtime.getCompiler().getTarget());
+                    SnippetInstaller installer = new SnippetInstaller(runtime, runtime.getGraalRuntime().getTarget());
                     GraalIntrinsics.installIntrinsics(installer);
                     runtime.installSnippets(installer);
                 }
@@ -288,7 +289,7 @@
         CompilationStatistics.clear("final");
         MethodEntryCounters.printCounters(graalRuntime);
         HotSpotXirGenerator.printCounters(TTY.out().out());
-        CheckCastSnippets.printCounters(TTY.out().out());
+        SnippetCounter.printGroups(TTY.out().out());
     }
 
     private void flattenChildren(DebugValueMap map, DebugValueMap globalMap) {
@@ -411,7 +412,7 @@
     public JavaField createJavaField(JavaType holder, String name, JavaType type, int offset, int flags) {
         if (offset != -1) {
             HotSpotResolvedJavaType resolved = (HotSpotResolvedJavaType) holder;
-            return resolved.createRiField(name, type, offset, flags);
+            return resolved.createField(name, type, offset, flags);
         }
         return new UnresolvedField(holder, name, type);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/counters/MethodEntryCounters.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/counters/MethodEntryCounters.java	Wed Jul 18 10:50:57 2012 -0700
@@ -80,8 +80,8 @@
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
             int start = masm.codeBuffer.position();
-            int off = Unsafe.getUnsafe().arrayBaseOffset(long[].class);
-            int scale = Unsafe.getUnsafe().arrayIndexScale(long[].class);
+            int off = Unsafe.ARRAY_LONG_BASE_OFFSET;
+            int scale = Unsafe.ARRAY_LONG_INDEX_SCALE;
 
             AMD64Move.move(tasm, masm, counterArr, Constant.forObject(counter.counts));
             AMD64Move.load(tasm, masm, callerPc, new Address(Kind.Long, AMD64.rbp.asValue(Kind.Long), 8), null);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCompiledMethod.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCompiledMethod.java	Wed Jul 18 10:50:57 2012 -0700
@@ -24,11 +24,12 @@
 
 import java.lang.reflect.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
 
 /**
- * Implementation of RiCompiledMethod for HotSpot.
+ * Implementation of {@link InstalledCode} for HotSpot.
  * Stores a reference to the nmethod which contains the compiled code.
  * The nmethod also stores a weak reference to the HotSpotCompiledMethod
  * instance which is necessary to keep the nmethod from being unloaded.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Wed Jul 18 10:50:57 2012 -0700
@@ -26,7 +26,7 @@
 import com.oracle.graal.hotspot.*;
 
 /**
- * Implementation of RiConstantPool for HotSpot.
+ * Implementation of {@link ConstantPool} for HotSpot.
  */
 public class HotSpotConstantPool extends CompilerObject implements ConstantPool {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java	Wed Jul 18 10:50:57 2012 -0700
@@ -36,16 +36,16 @@
  * This class implements the graph caching system for the HotSpot platform.
  *
  * This implementation does not use a map to store the actual cached graphs. The problem is that such maps keep the
- * graph, and therefore the RiResolvedMethod referenced from the graph, alive. For some applications and benchmarks this
+ * graph, and therefore the {@link ResolvedJavaMethod} referenced from the graph, alive. For some applications and benchmarks this
  * is a problem, e.g., the DaCapoScala "scalatest" benchmark will quickly run out of perm gen because of this.
  *
- * This cannot be solved with a WeakHashMap<RiResolvedMethod, Graph>, since the values within the map will keep the keys
+ * This cannot be solved with a {@code WeakHashMap<ResolvedJavaMethod, Graph>}, since the values within the map will keep the keys
  * alive. In order for this to work we would require a weak map in which the "strongness" of the value references
  * depends upon the reachability of the keys.
  *
- * Therefore the graph cache is implemented in such a way that it stores its cache entries within the RiResolvedMethod.
+ * Therefore the graph cache is implemented in such a way that it stores its cache entries within the {@link ResolvedJavaMethod}.
  * It uses the {@link ResolvedJavaMethod#compilerStorage()} map with the HotSpotGraphCache instance as key.
- * The cached graph will be kept alive as long as the RiResolvedMethod is alive, but does not prevent the method, and
+ * The cached graph will be kept alive as long as the {@link ResolvedJavaMethod} is alive, but does not prevent the method, and
  * therefore the class, from being unloaded.
  *
  * The {@link #cachedGraphIds} map is used to find the graphs that should be removed because of deoptimization, and to
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotJavaType.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotJavaType.java	Wed Jul 18 10:50:57 2012 -0700
@@ -26,7 +26,7 @@
 import com.oracle.graal.hotspot.*;
 
 /**
- * Common interface for all HotSpot RiType-implementations.
+ * Common interface for all HotSpot {@link JavaType} implementations.
  */
 public abstract class HotSpotJavaType extends CompilerObject implements JavaType {
     private static final long serialVersionUID = -4252886265301910771L;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Wed Jul 18 10:50:57 2012 -0700
@@ -358,7 +358,7 @@
             }
 
             totalCount += getTypesNotRecordedExecutionCount(data, position);
-            return createRiTypeProfile(types, counts, totalCount, entries);
+            return createTypeProfile(types, counts, totalCount, entries);
         }
 
         protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) {
@@ -367,7 +367,7 @@
             return getCounterValue(data, position);
         }
 
-        private static JavaTypeProfile createRiTypeProfile(ResolvedJavaType[] types, long[] counts, long totalCount, int entries) {
+        private static JavaTypeProfile createTypeProfile(ResolvedJavaType[] types, long[] counts, long totalCount, int entries) {
             if (entries <= 0 || totalCount < GraalOptions.MatureExecutionsTypeProfile) {
                 return null;
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java	Wed Jul 18 10:50:57 2012 -0700
@@ -25,7 +25,7 @@
 import com.oracle.graal.api.meta.*;
 
 /**
- * Implementation of RiMethod for unresolved HotSpot methods.
+ * Implementation of {@link JavaMethod} for unresolved HotSpot methods.
  */
 public final class HotSpotMethodUnresolved extends HotSpotMethod {
     private static final long serialVersionUID = 5610263481791970079L;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Wed Jul 18 10:50:57 2012 -0700
@@ -34,7 +34,7 @@
 import com.oracle.graal.hotspot.counters.*;
 
 /**
- * Implementation of RiMethod for resolved HotSpot methods.
+ * Implementation of {@link JavaMethod} for resolved HotSpot methods.
  */
 public final class HotSpotResolvedJavaMethod extends HotSpotMethod implements ResolvedJavaMethod {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java	Wed Jul 18 10:50:57 2012 -0700
@@ -31,7 +31,7 @@
 import com.oracle.graal.hotspot.*;
 
 /**
- * Implementation of RiType for resolved non-primitive HotSpot classes.
+ * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes.
  */
 public final class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType {
 
@@ -217,7 +217,7 @@
         return instanceSize;
     }
 
-    public synchronized ResolvedJavaField createRiField(String fieldName, JavaType type, int offset, int flags) {
+    public synchronized ResolvedJavaField createField(String fieldName, JavaType type, int offset, int flags) {
         ResolvedJavaField result = null;
 
         long id = offset + ((long) flags << 32);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Wed Jul 18 10:50:57 2012 -0700
@@ -46,6 +46,7 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.snippets.*;
@@ -58,13 +59,13 @@
     public final HotSpotVMConfig config;
     final HotSpotRegisterConfig regConfig;
     private final HotSpotRegisterConfig globalStubRegConfig;
-    private final HotSpotGraalRuntime compiler;
+    private final HotSpotGraalRuntime graalRuntime;
     private CheckCastSnippets.Templates checkcastSnippets;
     private NewObjectSnippets.Templates newObjectSnippets;
 
-    public HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime compiler) {
+    public HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) {
         this.config = config;
-        this.compiler = compiler;
+        this.graalRuntime = graalRuntime;
         regConfig = new HotSpotRegisterConfig(config, false);
         globalStubRegConfig = new HotSpotRegisterConfig(config, true);
 
@@ -78,18 +79,18 @@
         installer.install(CheckCastSnippets.class);
         installer.install(NewObjectSnippets.class);
         checkcastSnippets = new CheckCastSnippets.Templates(this);
-        newObjectSnippets = new NewObjectSnippets.Templates(this, compiler.getTarget(), config.useTLAB);
+        newObjectSnippets = new NewObjectSnippets.Templates(this, graalRuntime.getTarget(), config.useTLAB);
     }
 
 
-    public HotSpotGraalRuntime getCompiler() {
-        return compiler;
+    public HotSpotGraalRuntime getGraalRuntime() {
+        return graalRuntime;
     }
 
     @Override
     public String disassemble(CodeInfo info, CompilationResult tm) {
         byte[] code = info.code();
-        TargetDescription target = compiler.getTarget();
+        TargetDescription target = graalRuntime.getTarget();
         HexCodeFile hcf = new HexCodeFile(code, info.start(), target.arch.name, target.wordSize * 8);
         if (tm != null) {
             HexCodeFile.addAnnotations(hcf, tm.annotations());
@@ -181,12 +182,12 @@
 
     @Override
     public ResolvedJavaType getResolvedJavaType(Kind kind) {
-        return (ResolvedJavaType) compiler.getCompilerToVM().getType(kind.toJavaClass());
+        return (ResolvedJavaType) graalRuntime.getCompilerToVM().getType(kind.toJavaClass());
     }
 
     @Override
     public ResolvedJavaType getTypeOf(Constant constant) {
-        return (ResolvedJavaType) compiler.getCompilerToVM().getJavaType(constant);
+        return (ResolvedJavaType) graalRuntime.getCompilerToVM().getJavaType(constant);
     }
 
     @Override
@@ -197,7 +198,7 @@
 
     @Override
     public boolean areConstantObjectsEqual(Constant x, Constant y) {
-        return compiler.getCompilerToVM().compareConstantObjects(x, y);
+        return graalRuntime.getCompilerToVM().compareConstantObjects(x, y);
     }
 
     @Override
@@ -221,7 +222,7 @@
 
     @Override
     public int getArrayLength(Constant array) {
-        return compiler.getCompilerToVM().getArrayLength(array);
+        return graalRuntime.getCompilerToVM().getArrayLength(array);
     }
 
     @Override
@@ -231,6 +232,43 @@
             ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n;
             SafeReadNode safeReadArrayLength = safeReadArrayLength(arrayLengthNode.array(), StructuredGraph.INVALID_GRAPH_ID);
             graph.replaceFixedWithFixed(arrayLengthNode, safeReadArrayLength);
+        } else if (n instanceof Invoke) {
+            if (!GraalOptions.XIRLowerInvokes) {
+                Invoke invoke = (Invoke) n;
+                MethodCallTargetNode callTarget = invoke.callTarget();
+                NodeInputList<ValueNode> parameters = callTarget.arguments();
+                ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0);
+                if (!callTarget.isStatic() && receiver.kind() == Kind.Object && !receiver.objectStamp().nonNull()) {
+                    invoke.node().dependencies().add(tool.createNullCheckGuard(receiver, invoke.leafGraphId()));
+                }
+
+                if (callTarget.invokeKind() == InvokeKind.Virtual &&
+                    GraalOptions.InlineVTableStubs &&
+                    (GraalOptions.AlwaysInlineVTableStubs || invoke.isMegamorphic())) {
+
+                    HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod();
+                    if (!hsMethod.holder().isInterface()) {
+                        // We use LocationNode.ANY_LOCATION for the reads that access the vtable entry and the compiled code entry
+                        // as HotSpot does not guarantee they are final values.
+                        int vtableEntryOffset = hsMethod.vtableEntryOffset();
+                        assert vtableEntryOffset != 0;
+                        SafeReadNode hub = safeReadHub(graph, receiver, StructuredGraph.INVALID_GRAPH_ID);
+                        Kind wordKind = graalRuntime.getTarget().wordKind;
+                        Stamp nonNullWordStamp = StampFactory.forWord(wordKind, true);
+                        ReadNode methodOop = graph.add(new ReadNode(hub, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, vtableEntryOffset, graph), nonNullWordStamp));
+                        ReadNode compiledEntry = graph.add(new ReadNode(methodOop, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), nonNullWordStamp));
+                        callTarget.setComputedAddress(compiledEntry);
+
+                        // Append the methodOop to the arguments so that it can be explicitly passed in RBX as
+                        // is required for all compiled calls in HotSpot.
+                        callTarget.arguments().add(methodOop);
+
+                        graph.addBeforeFixed(invoke.node(), hub);
+                        graph.addAfterFixed(hub, methodOop);
+                        graph.addAfterFixed(methodOop, compiledEntry);
+                    }
+                }
+            }
         } else if (n instanceof LoadFieldNode) {
             LoadFieldNode field = (LoadFieldNode) n;
             int displacement = ((HotSpotResolvedJavaField) field.field()).offset();
@@ -253,7 +291,7 @@
             graph.replaceFixedWithFixed(storeField, memoryWrite);
 
             FixedWithNextNode last = memoryWrite;
-            if (field.kind() == Kind.Object && !memoryWrite.value().isNullConstant()) {
+            if (field.kind() == Kind.Object && !memoryWrite.value().objectStamp().alwaysNull()) {
                 FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(memoryWrite.object()));
                 graph.addAfterFixed(memoryWrite, writeBarrier);
                 last = writeBarrier;
@@ -268,7 +306,7 @@
             // Separate out GC barrier semantics
             CompareAndSwapNode cas = (CompareAndSwapNode) n;
             ValueNode expected = cas.expected();
-            if (expected.kind() == Kind.Object && !cas.newValue().isNullConstant()) {
+            if (expected.kind() == Kind.Object && !cas.newValue().objectStamp().alwaysNull()) {
                 ResolvedJavaType type = cas.object().objectStamp().type();
                 if (type != null && !type.isArrayClass() && type.toJava() != Object.class) {
                     // Use a field write barrier since it's not an array store
@@ -299,7 +337,7 @@
             ValueNode value = storeIndexed.value();
             CheckCastNode checkcast = null;
             ValueNode array = storeIndexed.array();
-            if (elementKind == Kind.Object && !value.isNullConstant()) {
+            if (elementKind == Kind.Object && !value.objectStamp().alwaysNull()) {
                 // Store check!
                 ResolvedJavaType arrayType = array.objectStamp().type();
                 if (arrayType != null && array.objectStamp().isExactType()) {
@@ -328,7 +366,7 @@
 
             graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
 
-            if (elementKind == Kind.Object && !value.isNullConstant()) {
+            if (elementKind == Kind.Object && !value.objectStamp().alwaysNull()) {
                 graph.addAfterFixed(memoryWrite, graph.add(new ArrayWriteBarrier(array, arrayLocation)));
             }
         } else if (n instanceof UnsafeLoadNode) {
@@ -347,7 +385,7 @@
             WriteNode write = graph.add(new WriteNode(object, store.value(), location));
             write.setStateAfter(store.stateAfter());
             graph.replaceFixedWithFixed(store, write);
-            if (write.value().kind() == Kind.Object && !write.value().isNullConstant()) {
+            if (write.value().kind() == Kind.Object && !write.value().objectStamp().alwaysNull()) {
                 ResolvedJavaType type = object.objectStamp().type();
                 WriteBarrier writeBarrier;
                 if (type != null && !type.isArrayClass() && type.toJava() != Object.class) {
@@ -366,15 +404,15 @@
             memoryRead.dependencies().add(tool.createNullCheckGuard(objectClassNode.object(), StructuredGraph.INVALID_GRAPH_ID));
             graph.replaceFixed(objectClassNode, memoryRead);
         } else if (n instanceof CheckCastNode) {
-            if (shouldLower(graph, GraalOptions.HIRLowerCheckcast)) {
+            if (matches(graph, GraalOptions.HIRLowerCheckcast)) {
                 checkcastSnippets.lower((CheckCastNode) n, tool);
             }
         } else if (n instanceof NewInstanceNode) {
-            if (shouldLower(graph, GraalOptions.HIRLowerNewInstance)) {
+            if (matches(graph, GraalOptions.HIRLowerNewInstance)) {
                 newObjectSnippets.lower((NewInstanceNode) n, tool);
             }
         } else if (n instanceof NewArrayNode) {
-            if (shouldLower(graph, GraalOptions.HIRLowerNewArray)) {
+            if (matches(graph, GraalOptions.HIRLowerNewArray)) {
                 newObjectSnippets.lower((NewArrayNode) n, tool);
             }
         } else if (n instanceof TLABAllocateNode) {
@@ -388,13 +426,13 @@
         }
     }
 
-    private static boolean shouldLower(StructuredGraph graph, String option) {
-        if (option != null) {
-            if (option.length() == 0) {
+    private static boolean matches(StructuredGraph graph, String filter) {
+        if (filter != null) {
+            if (filter.length() == 0) {
                 return true;
             }
             ResolvedJavaMethod method = graph.method();
-            return method != null && MetaUtil.format("%H.%n", method).contains(option);
+            return method != null && MetaUtil.format("%H.%n", method).contains(filter);
         }
         return false;
     }
@@ -474,7 +512,7 @@
     }
 
     public ResolvedJavaType getResolvedJavaType(Class<?> clazz) {
-        return (ResolvedJavaType) compiler.getCompilerToVM().getType(clazz);
+        return (ResolvedJavaType) graalRuntime.getCompilerToVM().getType(clazz);
     }
 
     public Object asCallTarget(Object target) {
@@ -482,31 +520,31 @@
     }
 
     public long getMaxCallTargetOffset(RuntimeCall rtcall) {
-        return compiler.getCompilerToVM().getMaxCallTargetOffset(rtcall);
+        return graalRuntime.getCompilerToVM().getMaxCallTargetOffset(rtcall);
     }
 
     public ResolvedJavaMethod getResolvedJavaMethod(Method reflectionMethod) {
-        return (ResolvedJavaMethod) compiler.getCompilerToVM().getJavaMethod(reflectionMethod);
+        return (ResolvedJavaMethod) graalRuntime.getCompilerToVM().getJavaMethod(reflectionMethod);
     }
 
-    private static HotSpotCodeInfo makeInfo(ResolvedJavaMethod method, CompilationResult code, CodeInfo[] info) {
+    private static HotSpotCodeInfo makeInfo(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info) {
         HotSpotCodeInfo hsInfo = null;
         if (info != null && info.length > 0) {
-            hsInfo = new HotSpotCodeInfo(code, (HotSpotResolvedJavaMethod) method);
+            hsInfo = new HotSpotCodeInfo(compResult, (HotSpotResolvedJavaMethod) method);
             info[0] = hsInfo;
         }
         return hsInfo;
     }
 
-    public void installMethod(ResolvedJavaMethod method, CompilationResult code, CodeInfo[] info) {
-        HotSpotCodeInfo hsInfo = makeInfo(method, code, info);
-        compiler.getCompilerToVM().installMethod(new HotSpotTargetMethod((HotSpotResolvedJavaMethod) method, code), true, hsInfo);
+    public void installMethod(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info) {
+        HotSpotCodeInfo hsInfo = makeInfo(method, compResult, info);
+        graalRuntime.getCompilerToVM().installMethod(new HotSpotCompilationResult((HotSpotResolvedJavaMethod) method, compResult), true, hsInfo);
     }
 
     @Override
-    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult code, CodeInfo[] info) {
-        HotSpotCodeInfo hsInfo = makeInfo(method, code, info);
-        return compiler.getCompilerToVM().installMethod(new HotSpotTargetMethod((HotSpotResolvedJavaMethod) method, code), false, hsInfo);
+    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info) {
+        HotSpotCodeInfo hsInfo = makeInfo(method, compResult, info);
+        return graalRuntime.getCompilerToVM().installMethod(new HotSpotCompilationResult((HotSpotResolvedJavaMethod) method, compResult), false, hsInfo);
     }
 
     @Override
@@ -515,12 +553,6 @@
     }
 
     @Override
-    public CompilationResult compile(ResolvedJavaMethod method, StructuredGraph graph) {
-        OptimisticOptimizations optimisticOpts = OptimisticOptimizations.ALL;
-        return compiler.getCompiler().compileMethod(method, graph, -1, compiler.getCache(), compiler.getVMToCompiler().createPhasePlan(optimisticOpts), optimisticOpts);
-    }
-
-    @Override
     public int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) {
         final int actionShift = 0;
         final int reasonShift = 3;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypePrimitive.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypePrimitive.java	Wed Jul 18 10:50:57 2012 -0700
@@ -30,7 +30,7 @@
 import com.oracle.graal.hotspot.*;
 
 /**
- * Implementation of RiType for primitive HotSpot types.
+ * Implementation of {@link JavaType} for primitive HotSpot types.
  */
 public final class HotSpotTypePrimitive extends HotSpotJavaType implements ResolvedJavaType {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypeUnresolved.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypeUnresolved.java	Wed Jul 18 10:50:57 2012 -0700
@@ -27,7 +27,7 @@
 import com.oracle.graal.hotspot.*;
 
 /**
- * Implementation of RiType for unresolved HotSpot classes.
+ * Implementation of {@link JavaType} for unresolved HotSpot classes.
  */
 public class HotSpotTypeUnresolved extends HotSpotJavaType {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1049 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.meta;
-
-import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.hotspot.meta.TemplateFlag.*;
-
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-import sun.misc.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.Address.*;
-import com.oracle.graal.api.code.Register.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.cri.xir.*;
-import com.oracle.max.cri.xir.CiXirAssembler.XirConstant;
-import com.oracle.max.cri.xir.CiXirAssembler.XirLabel;
-import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
-import com.oracle.max.cri.xir.CiXirAssembler.XirOperand;
-import com.oracle.max.cri.xir.CiXirAssembler.XirParameter;
-
-public class HotSpotXirGenerator implements RiXirGenerator {
-
-    // this needs to correspond to graal_CodeInstaller.hpp
-    // @formatter:off
-    public static final Integer MARK_VERIFIED_ENTRY            = 0x0001;
-    public static final Integer MARK_UNVERIFIED_ENTRY          = 0x0002;
-    public static final Integer MARK_OSR_ENTRY                 = 0x0003;
-    public static final Integer MARK_UNWIND_ENTRY              = 0x0004;
-    public static final Integer MARK_EXCEPTION_HANDLER_ENTRY   = 0x0005;
-    public static final Integer MARK_DEOPT_HANDLER_ENTRY       = 0x0006;
-
-    public static final Integer MARK_STATIC_CALL_STUB          = 0x1000;
-
-    public static final Integer MARK_INVOKEINTERFACE           = 0x2001;
-    public static final Integer MARK_INVOKESTATIC              = 0x2002;
-    public static final Integer MARK_INVOKESPECIAL             = 0x2003;
-    public static final Integer MARK_INVOKEVIRTUAL             = 0x2004;
-
-    public static final Integer MARK_IMPLICIT_NULL             = 0x3000;
-    public static final Integer MARK_POLL_NEAR                 = 0x3001;
-    public static final Integer MARK_POLL_RETURN_NEAR          = 0x3002;
-    public static final Integer MARK_POLL_FAR                  = 0x3003;
-    public static final Integer MARK_POLL_RETURN_FAR           = 0x3004;
-
-    // @formatter:on
-
-    private final HotSpotVMConfig config;
-    private final TargetDescription target;
-    private final RegisterConfig registerConfig;
-    private final HotSpotGraalRuntime compiler;
-
-
-    private CiXirAssembler globalAsm;
-
-    public HotSpotXirGenerator(HotSpotVMConfig config, TargetDescription target, RegisterConfig registerConfig, HotSpotGraalRuntime compiler) {
-        this.config = config;
-        this.target = target;
-        this.registerConfig = registerConfig;
-        this.compiler = compiler;
-    }
-
-    private XirConstant wordConst(CiXirAssembler asm, long value) {
-        if (target.wordKind == Kind.Long) {
-            return asm.createConstant(Constant.forLong(value));
-        } else {
-            assert target.wordKind == Kind.Int;
-            return asm.createConstant(Constant.forInt((int) value));
-        }
-    }
-
-    private XirArgument wordArg(long value) {
-        if (target.wordKind == Kind.Long) {
-            return XirArgument.forLong(value);
-        } else {
-            assert target.wordKind == Kind.Int;
-            return XirArgument.forInt((int) value);
-        }
-    }
-
-    private SimpleTemplates invokeInterfaceTemplates = new SimpleTemplates(NULL_CHECK) {
-
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags) {
-            asm.restart();
-            XirParameter receiver = asm.createInputParameter("receiver", Kind.Object);
-            XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind);
-            XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
-            XirOperand tempO = asm.createRegister("tempO", Kind.Object, AMD64.rax);
-
-            if (is(NULL_CHECK, flags)) {
-                asm.mark(MARK_IMPLICIT_NULL);
-                asm.pload(target.wordKind, temp, receiver, true);
-            }
-            asm.mark(MARK_INVOKEINTERFACE);
-            asm.mov(tempO, asm.createConstant(Constant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ)));
-
-            return asm.finishTemplate(addr, "invokeinterface");
-        }
-    };
-
-    private SimpleTemplates invokeVirtualTemplates = new SimpleTemplates(NULL_CHECK) {
-
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags) {
-            asm.restart();
-            XirParameter receiver = asm.createInputParameter("receiver", Kind.Object);
-            XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind);
-            XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
-            XirOperand tempO = asm.createRegister("tempO", Kind.Object, AMD64.rax);
-
-            if (is(NULL_CHECK, flags)) {
-                asm.mark(MARK_IMPLICIT_NULL);
-                asm.pload(target.wordKind, temp, receiver, true);
-            }
-            asm.mark(MARK_INVOKEVIRTUAL);
-            asm.mov(tempO, asm.createConstant(Constant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ)));
-
-            return asm.finishTemplate(addr, "invokevirtual");
-        }
-    };
-
-    private IndexTemplates inlinedInvokeVirtualTemplates = new IndexTemplates(NULL_CHECK) {
-
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags, int vtableEntryOffset) {
-            asm.restart();
-            XirParameter receiver = asm.createInputParameter("receiver", Kind.Object);
-            XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
-            XirOperand method = asm.createRegisterTemp("method", Kind.Object, AMD64.rbx);
-
-            // load class from receiver
-            if (is(NULL_CHECK, flags)) {
-                asm.mark(MARK_IMPLICIT_NULL);
-            }
-            asm.pload(target.wordKind, temp, receiver, asm.i(config.hubOffset), true);
-            // load vtable entry
-            asm.pload(target.wordKind, method, temp, asm.i(vtableEntryOffset), false);
-            // load entry point from methodOop
-            asm.mark(MARK_IMPLICIT_NULL);
-            asm.pload(target.wordKind, temp, method, asm.i(config.methodCompiledEntryOffset), true);
-            asm.mark(MARK_INVOKEVIRTUAL);
-
-            return asm.finishTemplate(temp, "invokevirtual");
-        }
-    };
-
-    private SimpleTemplates invokeSpecialTemplates = new SimpleTemplates(NULL_CHECK) {
-
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags) {
-            asm.restart();
-            XirParameter receiver = asm.createInputParameter("receiver", Kind.Object);
-            XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind);
-            XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
-            XirLabel stub = asm.createOutOfLineLabel("call stub");
-
-            if (is(NULL_CHECK, flags)) {
-                asm.mark(MARK_IMPLICIT_NULL);
-                asm.pload(target.wordKind, temp, receiver, true);
-            }
-            asm.mark(MARK_INVOKESPECIAL);
-
-            // -- out of line -------------------------------------------------------
-            asm.bindOutOfLine(stub);
-            XirOperand method = asm.createRegisterTemp("method", target.wordKind, AMD64.rbx);
-            asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE);
-            asm.mov(method, wordConst(asm, 0));
-            XirLabel dummy = asm.createOutOfLineLabel("dummy");
-            asm.jmp(dummy);
-            asm.bindOutOfLine(dummy);
-
-            return asm.finishTemplate(addr, "invokespecial");
-        }
-    };
-
-    private SimpleTemplates invokeStaticTemplates = new SimpleTemplates() {
-
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags) {
-            asm.restart();
-            XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind);
-
-            XirLabel stub = asm.createOutOfLineLabel("call stub");
-            asm.mark(MARK_INVOKESTATIC);
-
-            // -- out of line -------------------------------------------------------
-            asm.bindOutOfLine(stub);
-            XirOperand method = asm.createRegisterTemp("method", target.wordKind, AMD64.rbx);
-            asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE);
-            asm.mov(method, wordConst(asm, 0));
-            XirLabel dummy = asm.createOutOfLineLabel("dummy");
-            asm.jmp(dummy);
-            asm.bindOutOfLine(dummy);
-
-            return asm.finishTemplate(addr, "invokestatic");
-        }
-    };
-
-    private SimpleTemplates monitorEnterTemplates = new SimpleTemplates(NULL_CHECK) {
-
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags) {
-            asm.restart(Kind.Void);
-            XirParameter object = asm.createInputParameter("object", Kind.Object);
-            XirParameter lock = asm.createInputParameter("lock", target.wordKind);
-
-            if (is(NULL_CHECK, flags)) {
-                asm.mark(MARK_IMPLICIT_NULL);
-                asm.pload(target.wordKind, asm.createTemp("temp", target.wordKind), object, true);
-            }
-
-
-            // (thomaswue) It is important to use for this runtime call the debug info AFTER the monitor enter. Otherwise the monitor object
-            // is not correctly garbage collected.
-            final boolean useInfoAfter = true;
-
-            if (config.useFastLocking) {
-                useRegisters(asm, AMD64.rax, AMD64.rbx);
-                useRegisters(asm, getGeneralParameterRegister(0));
-                useRegisters(asm, getGeneralParameterRegister(1));
-                asm.callRuntime(config.fastMonitorEnterStub, null, useInfoAfter, object, lock);
-            } else {
-                asm.reserveOutgoingStack(target.wordSize * 2);
-                XirOperand rsp = asm.createRegister("rsp", target.wordKind, asRegister(AMD64.RSP));
-                asm.pstore(Kind.Object, rsp, asm.i(target.wordSize), object, false);
-                asm.pstore(target.wordKind, rsp, asm.i(0), lock, false);
-                asm.callRuntime(config.monitorEnterStub, null, useInfoAfter);
-            }
-
-            return asm.finishTemplate("monitorEnter");
-        }
-    };
-
-    private Register getGeneralParameterRegister(int index) {
-        return registerConfig.getCallingConventionRegisters(CallingConvention.Type.RuntimeCall, RegisterFlag.CPU)[index];
-    }
-
-    private SimpleTemplates monitorExitTemplates = new SimpleTemplates(NULL_CHECK) {
-
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags) {
-            asm.restart(Kind.Void);
-            XirParameter object = asm.createInputParameter("object", Kind.Object);
-            XirParameter lock = asm.createInputParameter("lock", target.wordKind);
-
-            if (config.useFastLocking) {
-                useRegisters(asm, AMD64.rax, AMD64.rbx);
-                useRegisters(asm, getGeneralParameterRegister(0));
-                useRegisters(asm, getGeneralParameterRegister(1));
-                asm.callRuntime(config.fastMonitorExitStub, null, object, lock);
-            } else {
-                asm.reserveOutgoingStack(target.wordSize);
-                asm.pstore(target.wordKind, asm.createRegister("rsp", target.wordKind, asRegister(AMD64.RSP)), asm.i(0), lock, false);
-                asm.callRuntime(config.monitorExitStub, null);
-            }
-
-            return asm.finishTemplate("monitorExit");
-        }
-    };
-
-    private final IndexTemplates newInstanceTemplates = new IndexTemplates() {
-
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags, int size) {
-            XirOperand result = asm.restart(target.wordKind);
-            XirOperand hub = asm.createInputParameter("hub", Kind.Object);
-
-            XirOperand temp1 = asm.createRegisterTemp("temp1", target.wordKind, AMD64.rcx);
-            XirOperand temp1o = asm.createRegister("temp1o", Kind.Object, AMD64.rcx);
-            XirOperand temp2 = asm.createRegisterTemp("temp2", target.wordKind, AMD64.rbx);
-            XirOperand temp2i = asm.createRegister("temp2i", Kind.Int, AMD64.rbx);
-            useRegisters(asm, AMD64.rsi);
-            XirLabel tlabFull = asm.createOutOfLineLabel("tlab full");
-            XirLabel resume = asm.createInlineLabel("resume");
-
-            // check if the class is already initialized
-            asm.pload(Kind.Int, temp2i, hub, asm.i(config.klassStateOffset), false);
-            asm.jneq(tlabFull, temp2i, asm.i(config.klassStateFullyInitialized));
-
-            XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15);
-            asm.pload(target.wordKind, result, thread, asm.i(config.threadTlabTopOffset), false);
-            asm.add(temp1, result, wordConst(asm, size));
-            asm.pload(target.wordKind, temp2, thread, asm.i(config.threadTlabEndOffset), false);
-
-            asm.jgt(tlabFull, temp1, temp2);
-            asm.pstore(target.wordKind, thread, asm.i(config.threadTlabTopOffset), temp1, false);
-
-            asm.bindInline(resume);
-
-            asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false);
-            asm.pstore(target.wordKind, result, asm.i(config.markOffset), temp1, false);
-            asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory
-            asm.pstore(Kind.Object, result, asm.i(config.hubOffset), temp1o, false);
-
-            if (size > 2 * target.wordSize) {
-                asm.mov(temp1, wordConst(asm, 0));
-                for (int offset = 2 * target.wordSize; offset < size; offset += target.wordSize) {
-                    asm.pstore(target.wordKind, result, asm.i(offset), temp1, false);
-                }
-            }
-
-            // -- out of line -------------------------------------------------------
-            asm.bindOutOfLine(tlabFull);
-            XirOperand arg = asm.createRegisterTemp("runtime call argument", Kind.Object, AMD64.rdx);
-            asm.mov(arg, hub);
-            useRegisters(asm, AMD64.rax);
-            asm.callRuntime(config.newInstanceStub, result);
-            asm.jmp(resume);
-
-            return asm.finishTemplate("new instance");
-        }
-    };
-
-    private SimpleTemplates newObjectArrayTemplates = new SimpleTemplates() {
-
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags) {
-            emitNewTypeArray(asm, Kind.Object, config.useFastNewObjectArray, config.newObjectArrayStub);
-            return asm.finishTemplate("newObjectArray");
-        }
-    };
-
-    private void emitNewTypeArray(CiXirAssembler asm, Kind kind, boolean useFast, long slowPathStub) {
-        XirOperand result = asm.restart(target.wordKind);
-
-        XirParameter lengthParam = asm.createInputParameter("length", Kind.Int, true);
-
-        XirOperand length = asm.createRegisterTemp("length", Kind.Int, AMD64.rbx);
-        XirOperand hub = asm.createRegisterTemp("hub", Kind.Object, AMD64.rdx);
-
-        // Registers rsi, rcx, rdi, and rax are needed by the runtime call.
-        // Hub needs to be on rdx, length on rbx.
-        XirOperand temp1 = asm.createRegisterTemp("temp1", target.wordKind, AMD64.rcx);
-        XirOperand temp1o = asm.createRegister("temp1o", Kind.Object, AMD64.rcx);
-        XirOperand temp2 = asm.createRegisterTemp("temp2", target.wordKind, AMD64.rax);
-        XirOperand temp3 = asm.createRegisterTemp("temp3", target.wordKind, AMD64.rdi);
-        XirOperand size = asm.createRegisterTemp("size", Kind.Int, AMD64.rsi);
-
-        asm.mov(hub, asm.createConstantInputParameter("hub", Kind.Object));
-        asm.mov(length, lengthParam);
-
-        if (useFast) {
-
-            XirLabel slowPath = asm.createOutOfLineLabel("slowPath");
-
-            XirLabel done = asm.createInlineLabel("done");
-
-            // Check for negative array size.
-            // TODO: Also check for upper bound
-            asm.jlt(slowPath, length, asm.i(0));
-
-            final int aligning = target.wordSize;
-            final int arrayLengthOffset = target.wordSize * 2;
-            final int arrayElementOffset = kind.arrayBaseOffset();
-
-            // Calculate aligned size
-            asm.mov(size, length);
-            int scale = CodeUtil.log2(target.sizeInBytes(kind));
-            if (scale != 0) {
-                asm.shl(size, size, asm.i(scale));
-            }
-            asm.add(size, size, asm.i(arrayElementOffset + aligning - 1));
-            long mask = 0xFFFFFFFFL;
-            mask <<= CodeUtil.log2(aligning);
-            asm.and(size, size, asm.i((int) mask));
-
-            // Try tlab allocation
-            XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15);
-            asm.pload(target.wordKind, result, thread, asm.i(config.threadTlabTopOffset), false);
-            asm.add(temp1, result, size);
-            asm.pload(target.wordKind, temp2, thread, asm.i(config.threadTlabEndOffset), false);
-            asm.jgt(slowPath, temp1, temp2);
-            asm.pstore(target.wordKind, thread, asm.i(config.threadTlabTopOffset), temp1, false);
-
-            // Now the new object is in result, store mark word and klass
-            asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false);
-            asm.pstore(target.wordKind, result, asm.i(config.markOffset), temp1, false);
-            asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory
-            asm.pstore(Kind.Object, result, asm.i(config.hubOffset), temp1o, false);
-
-            // Store array length
-            asm.pstore(Kind.Int, result, asm.i(arrayLengthOffset), length, false);
-
-            // Initialize with 0
-            XirLabel top = asm.createInlineLabel("top");
-            asm.sub(size, size, asm.i(arrayElementOffset));
-            asm.shr(size, size, asm.i(Scale.Times8.log2));
-            asm.jeq(done, size, asm.i(0));
-            asm.xor(temp3, temp3, temp3);
-            asm.bindInline(top);
-            asm.pstore(target.wordKind, result, size, temp3, arrayElementOffset - target.wordSize, Scale.Times8, false);
-            asm.decAndJumpNotZero(top, size);
-
-            asm.bindInline(done);
-
-            // Slow path
-            asm.bindOutOfLine(slowPath);
-            asm.callRuntime(slowPathStub, result);
-            asm.jmp(done);
-        } else {
-            asm.callRuntime(slowPathStub, result);
-        }
-    }
-
-    private KindTemplates newTypeArrayTemplates = new KindTemplates() {
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags, Kind kind) {
-            emitNewTypeArray(asm, kind, config.useFastNewTypeArray, config.newTypeArrayStub);
-            return asm.finishTemplate("newTypeArray<" + kind.toString() + ">");
-        }
-    };
-
-    private final IndexTemplates multiNewArrayTemplate = new IndexTemplates() {
-
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags, int dimensions) {
-            XirOperand result = asm.restart(Kind.Object);
-
-            XirOperand hub = asm.createRegisterTemp("hub", Kind.Object, AMD64.rax);
-            XirOperand rank = asm.createRegisterTemp("rank", Kind.Int, AMD64.rbx);
-            XirOperand sizes = asm.createRegisterTemp("sizes", Kind.Long, AMD64.rcx);
-            XirOperand thread = asm.createRegisterTemp("thread", Kind.Long, AMD64.r15);
-            asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorageOffset));
-            for (int i = 0; i < dimensions; i++) {
-                XirParameter length = asm.createInputParameter("length" + i, Kind.Int, true);
-                asm.pstore(Kind.Int, sizes, asm.i(i * target.sizeInBytes(Kind.Int)), length, false);
-            }
-
-            asm.mov(hub, asm.createConstantInputParameter("hub", Kind.Object));
-
-            asm.mov(rank, asm.i(dimensions));
-            // not necessary because we already have a temp in rax:  useRegisters(asm, AMD64.rax);
-            asm.callRuntime(config.newMultiArrayStub, result);
-            return asm.finishTemplate("multiNewArray" + dimensions);
-        }
-    };
-
-    enum CheckcastCounter {
-        hintsHit("hit a hint type"),
-        hintsMissed("missed the hint types"),
-        exact("tested type is (statically) final"),
-        noHints_class("profile information is not used (test type is a class)"),
-        noHints_iface("profile information is not used (test type is an interface)"),
-        noHints_unknown("test type is not a compile-time constant"),
-        isNull("object tested is null"),
-        exception("type test failed with a ClassCastException");
-
-        public final String desc;
-
-        private CheckcastCounter(String desc) {
-            this.desc = desc;
-        }
-
-        static final CheckcastCounter[] VALUES = values();
-    }
-
-    private static final long[] checkcastCounters = new long[CheckcastCounter.VALUES.length];
-
-    private IndexTemplates checkCastTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) {
-
-        private void incCounter(CiXirAssembler asm, XirOperand counter, XirParameter counters, CheckcastCounter offset) {
-            int disp = Unsafe.getUnsafe().arrayBaseOffset(long[].class);
-            Scale scale = Scale.fromInt(Unsafe.getUnsafe().arrayIndexScale(long[].class));
-            XirConstant index = asm.i(offset.ordinal());
-            asm.pload(Kind.Long, counter, counters, index, disp, scale, false);
-            asm.add(counter, counter, asm.i(1));
-            asm.pstore(Kind.Long, counters, index, counter, disp, scale, false);
-        }
-
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) {
-            asm.restart(Kind.Void);
-            boolean exact = is(EXACT_HINTS, flags);
-            XirParameter counters = GraalOptions.CheckcastCounters ? asm.createConstantInputParameter("counters", Kind.Object) : null;
-            XirParameter object = asm.createInputParameter("object", Kind.Object);
-            final XirOperand hub = exact ? null : asm.createConstantInputParameter("hub", Kind.Object);
-
-            XirOperand objHub = asm.createTemp("objHub", Kind.Object);
-            XirOperand counter = counters != null ? asm.createTemp("counter", Kind.Long) : null;
-
-            XirLabel success = asm.createInlineLabel("success");
-            XirLabel slowPath = asm.createOutOfLineLabel("slow path");
-
-            if (is(NULL_CHECK, flags)) {
-                // null can be cast to anything
-                if (counters != null) {
-                    XirLabel isNotNull = asm.createInlineLabel("isNull");
-                    asm.jneq(isNotNull, object, asm.o(null));
-                    incCounter(asm, counter, counters, CheckcastCounter.isNull);
-                    asm.jmp(success);
-                    asm.bindInline(isNotNull);
-                } else {
-                    asm.jeq(success, object, asm.o(null));
-                }
-
-            }
-
-            asm.pload(Kind.Object, objHub, object, asm.i(config.hubOffset), false);
-            if (hintCount == 0) {
-                assert !exact;
-                if (counters != null) {
-                    CheckcastCounter cc;
-                    if (is(NULL_TYPE, flags)) {
-                        cc = CheckcastCounter.noHints_unknown;
-                    } else if (is(INTERFACE_TYPE, flags)) {
-                        cc = CheckcastCounter.noHints_iface;
-                    } else {
-                        cc = CheckcastCounter.noHints_class;
-                    }
-                    incCounter(asm, counter, counters, cc);
-                }
-
-                checkSubtype(asm, objHub, objHub, hub);
-                asm.jeq(slowPath, objHub, asm.o(null));
-                asm.bindInline(success);
-
-                // -- out of line -------------------------------------------------------
-                asm.bindOutOfLine(slowPath);
-            } else {
-                XirLabel hintsSuccess = counters == null ? success : asm.createInlineLabel("hintsSuccess");
-                XirOperand scratchObject = asm.createRegisterTemp("scratch", Kind.Object, AMD64.r10);
-                // if we get an exact match: succeed immediately
-                for (int i = 0; i < hintCount; i++) {
-                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, Kind.Object);
-                    asm.mov(scratchObject, hintHub);
-                    if (i < hintCount - 1) {
-                        asm.jeq(hintsSuccess, objHub, scratchObject);
-                    } else {
-                        asm.jneq(slowPath, objHub, scratchObject);
-                    }
-                }
-
-                if (counters != null) {
-                    asm.bindInline(hintsSuccess);
-                    incCounter(asm, counter, counters, exact ? CheckcastCounter.exact : CheckcastCounter.hintsHit);
-                }
-
-                asm.bindInline(success);
-
-                // -- out of line -------------------------------------------------------
-                asm.bindOutOfLine(slowPath);
-                if (!exact) {
-                    if (counters != null) {
-                        incCounter(asm, counter, counters, CheckcastCounter.hintsMissed);
-                    }
-                    checkSubtype(asm, objHub, objHub, hub);
-                    asm.jneq(success, objHub, asm.o(null));
-                }
-            }
-
-            if (counters != null) {
-                incCounter(asm, counter, counters, CheckcastCounter.exception);
-            }
-            DeoptimizationReason deoptReason = exact ? DeoptimizationReason.OptimizedTypeCheckViolated : DeoptimizationReason.ClassCastException;
-            XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10);
-            asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(DeoptimizationAction.InvalidateReprofile, deoptReason)));
-            asm.callRuntime(RuntimeCall.Deoptimize, null);
-            asm.shouldNotReachHere();
-
-            return asm.finishTemplate("checkcast");
-        }
-    };
-
-    private IndexTemplates instanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) {
-
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) {
-            asm.restart(Kind.Void);
-            XirParameter object = asm.createInputParameter("object", Kind.Object);
-            final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", Kind.Object);
-
-            XirOperand objHub = asm.createTemp("objHub", Kind.Object);
-
-            XirLabel trueSucc = asm.createInlineLabel(XirLabel.TrueSuccessor);
-            XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor);
-
-            if (is(NULL_CHECK, flags)) {
-                // null isn't "instanceof" anything
-                asm.jeq(falseSucc, object, asm.o(null));
-            }
-
-            asm.pload(Kind.Object, objHub, object, asm.i(config.hubOffset), false);
-            if (hintCount == 0) {
-                assert !is(EXACT_HINTS, flags);
-                checkSubtype(asm, objHub, objHub, hub);
-                asm.jeq(falseSucc, objHub, asm.o(null));
-                asm.jmp(trueSucc);
-            } else {
-                XirLabel slowPath = null;
-                XirOperand scratchObject = asm.createRegisterTemp("scratch", Kind.Object, AMD64.r10);
-
-                // if we get an exact match: succeed immediately
-                for (int i = 0; i < hintCount; i++) {
-                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, Kind.Object);
-                    asm.mov(scratchObject, hintHub);
-                    if (i < hintCount - 1) {
-                        asm.jeq(trueSucc, objHub, scratchObject);
-                    } else {
-                        if (is(EXACT_HINTS, flags)) {
-                            asm.jneq(falseSucc, objHub, scratchObject);
-                            asm.jmp(trueSucc);
-                        } else {
-                            slowPath = asm.createOutOfLineLabel("slow path");
-                            asm.jneq(slowPath, objHub, scratchObject);
-                            asm.jmp(trueSucc);
-                        }
-                    }
-                }
-
-                // -- out of line -------------------------------------------------------
-                if (slowPath != null) {
-                    asm.bindOutOfLine(slowPath);
-                    checkSubtype(asm, objHub, objHub, hub);
-                    asm.jeq(falseSucc, objHub, asm.o(null));
-                    asm.jmp(trueSucc);
-                }
-            }
-
-            return asm.finishTemplate("instanceof");
-        }
-    };
-
-    private IndexTemplates materializeInstanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) {
-
-        @Override
-        protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) {
-            XirOperand result = asm.restart(Kind.Int);
-            XirParameter object = asm.createInputParameter("object", Kind.Object);
-            final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", Kind.Object);
-            XirOperand trueValue = asm.createInputParameter("trueValue", Kind.Int);
-            XirOperand falseValue = asm.createInputParameter("falseValue", Kind.Int);
-
-            XirOperand objHub = asm.createTemp("objHub", Kind.Object);
-
-            XirLabel end = asm.createInlineLabel("end");
-            XirLabel falseSucc = asm.createInlineLabel("ko");
-
-            if (is(NULL_CHECK, flags)) {
-                // null isn't "instanceof" anything
-                asm.jeq(falseSucc, object, asm.o(null));
-            }
-
-            asm.pload(Kind.Object, objHub, object, asm.i(config.hubOffset), false);
-            asm.mov(result, trueValue);
-
-            if (hintCount == 0) {
-                assert !is(EXACT_HINTS, flags);
-                checkSubtype(asm, objHub, objHub, hub);
-                asm.jneq(end, objHub, asm.o(null));
-                asm.bindInline(falseSucc);
-                asm.mov(result, falseValue);
-                asm.bindInline(end);
-            } else {
-                XirLabel slowPath = null;
-                XirOperand scratchObject = asm.createRegisterTemp("scratch", Kind.Object, AMD64.r10);
-
-                // if we get an exact match: succeed immediately
-                for (int i = 0; i < hintCount; i++) {
-                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, Kind.Object);
-                    asm.mov(scratchObject, hintHub);
-                    if (i < hintCount - 1) {
-                        asm.jeq(end, objHub, scratchObject);
-                    } else {
-                        if (is(EXACT_HINTS, flags)) {
-                            asm.jeq(end, objHub, scratchObject);
-                        } else {
-                            slowPath = asm.createOutOfLineLabel("slow path");
-                            asm.jeq(end, objHub, scratchObject);
-                            asm.jmp(slowPath);
-                        }
-                    }
-                }
-                asm.bindInline(falseSucc);
-                asm.mov(result, falseValue);
-                asm.bindInline(end);
-
-                // -- out of line -------------------------------------------------------
-                if (slowPath != null) {
-                    asm.bindOutOfLine(slowPath);
-                    checkSubtype(asm, objHub, objHub, hub);
-                    asm.jeq(falseSucc, objHub, asm.o(null));
-                    asm.jmp(end);
-                }
-            }
-
-            return asm.finishTemplate("instanceof");
-        }
-    };
-
-    private SimpleTemplates typeCheckTemplates = new SimpleTemplates(NULL_CHECK) {
-       @Override
-       protected XirTemplate create(CiXirAssembler asm, long flags) {
-           asm.restart(Kind.Void);
-           XirParameter objHub = asm.createInputParameter("objectHub", Kind.Object);
-           XirOperand hub = asm.createConstantInputParameter("hub", Kind.Object);
-           XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor);
-
-           XirOperand checkHub = asm.createTemp("checkHub", Kind.Object);
-
-           if (is(NULL_CHECK, flags)) {
-               asm.mark(MARK_IMPLICIT_NULL);
-           }
-
-           asm.mov(checkHub, hub);
-           // if we get an exact match: continue.
-           asm.jneq(falseSucc, objHub, checkHub);
-
-           return asm.finishTemplate("typeCheck");
-       }
-    };
-
-    @Override
-    public XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, JavaMethod method) {
-        return new XirSnippet(invokeInterfaceTemplates.get(site), receiver, wordArg(0));
-    }
-
-    @Override
-    public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, JavaMethod method, boolean megamorph) {
-        int vtableEntryOffset = 0;
-
-        if (GraalOptions.InlineVTableStubs && (GraalOptions.AlwaysInlineVTableStubs || megamorph)) {
-            HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
-            if (!hsMethod.holder().isInterface()) {
-                vtableEntryOffset = hsMethod.vtableEntryOffset();
-            }
-        }
-        if (vtableEntryOffset > 0) {
-            return new XirSnippet(inlinedInvokeVirtualTemplates.get(site, vtableEntryOffset), receiver);
-        } else {
-            return new XirSnippet(invokeVirtualTemplates.get(site), receiver, wordArg(0));
-        }
-    }
-
-    @Override
-    public XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, JavaMethod method) {
-        return new XirSnippet(invokeSpecialTemplates.get(site), receiver, wordArg(0));
-    }
-
-    @Override
-    public XirSnippet genInvokeStatic(XirSite site, JavaMethod method) {
-        return new XirSnippet(invokeStaticTemplates.get(site), wordArg(0));
-    }
-
-    @Override
-    public XirSnippet genMonitorEnter(XirSite site, XirArgument receiver, XirArgument lockAddress) {
-        return new XirSnippet(monitorEnterTemplates.get(site), receiver, lockAddress);
-    }
-
-    @Override
-    public XirSnippet genMonitorExit(XirSite site, XirArgument receiver, XirArgument lockAddress) {
-        return new XirSnippet(monitorExitTemplates.get(site), receiver, lockAddress);
-    }
-
-    @Override
-    public XirSnippet genNewInstance(XirSite site, JavaType type) {
-        HotSpotResolvedJavaType resolvedType = (HotSpotResolvedJavaType) type;
-        int instanceSize = resolvedType.instanceSize();
-        assert instanceSize >= 0;
-        return new XirSnippet(newInstanceTemplates.get(site, instanceSize), XirArgument.forObject(resolvedType.klassOop()));
-    }
-
-    @Override
-    public XirSnippet genNewArray(XirSite site, XirArgument length, Kind elementKind, JavaType componentType, JavaType arrayType) {
-        if (elementKind == Kind.Object) {
-            assert arrayType instanceof ResolvedJavaType;
-            return new XirSnippet(newObjectArrayTemplates.get(site), length, XirArgument.forObject(((HotSpotJavaType) arrayType).klassOop()));
-        } else {
-            assert arrayType == null;
-            JavaType primitiveArrayType = compiler.getCompilerToVM().getPrimitiveArrayType(elementKind);
-            return new XirSnippet(newTypeArrayTemplates.get(site, elementKind), length, XirArgument.forObject(((HotSpotJavaType) primitiveArrayType).klassOop()));
-        }
-    }
-
-    @Override
-    public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, JavaType type) {
-        XirArgument[] params = Arrays.copyOf(lengths, lengths.length + 1);
-        params[lengths.length] = XirArgument.forObject(((HotSpotJavaType) type).klassOop());
-        return new XirSnippet(multiNewArrayTemplate.get(site, lengths.length), params);
-    }
-
-    @Override
-    public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile) {
-        final boolean useCounters = GraalOptions.CheckcastCounters;
-        TypeCheckHints hints = new TypeCheckHints(type, profile, site.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints);
-        int hintsLength = hints.types.length;
-        if (hintsLength == 0) {
-            if (useCounters) {
-                if (type == null) {
-                    return new XirSnippet(checkCastTemplates.get(site, 0, NULL_TYPE), XirArgument.forObject(checkcastCounters), receiver, hub);
-                } else if (type.isInterface()) {
-                    return new XirSnippet(checkCastTemplates.get(site, 0, INTERFACE_TYPE), XirArgument.forObject(checkcastCounters), receiver, hub);
-                } else {
-                    return new XirSnippet(checkCastTemplates.get(site, 0), XirArgument.forObject(checkcastCounters), receiver, hub);
-                }
-            } else {
-                return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub);
-            }
-        } else {
-            XirArgument[] params = new XirArgument[(useCounters ? 1 : 0) + hintsLength + (hints.exact ? 1 : 2)];
-            int i = 0;
-            if (useCounters) {
-                params[i++] = XirArgument.forObject(checkcastCounters);
-            }
-            params[i++] = receiver;
-            if (!hints.exact) {
-                params[i++] = hub;
-            }
-            for (ResolvedJavaType hint : hints.types) {
-                params[i++] = XirArgument.forObject(((HotSpotJavaType) hint).klassOop());
-            }
-            XirTemplate template = hints.exact ? checkCastTemplates.get(site, hintsLength, EXACT_HINTS) : checkCastTemplates.get(site, hintsLength);
-            return new XirSnippet(template, params);
-        }
-    }
-
-    @Override
-    public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile) {
-        TypeCheckHints hints = new TypeCheckHints(type, profile, site.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints);
-        int hintsLength = hints.types.length;
-        if (hintsLength == 0) {
-            return new XirSnippet(instanceOfTemplates.get(site, 0), object, hub);
-        } else {
-            XirArgument[] params = new XirArgument[hintsLength + (hints.exact ? 1 : 2)];
-            int i = 0;
-            params[i++] = object;
-            if (!hints.exact) {
-                params[i++] = hub;
-            }
-            for (ResolvedJavaType hint : hints.types) {
-                params[i++] = XirArgument.forObject(((HotSpotJavaType) hint).klassOop());
-            }
-            XirTemplate template = hints.exact ? instanceOfTemplates.get(site, hintsLength, EXACT_HINTS) : instanceOfTemplates.get(site, hintsLength);
-            return new XirSnippet(template, params);
-        }
-    }
-
-    @Override
-    public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, ResolvedJavaType type, JavaTypeProfile profile) {
-        TypeCheckHints hints = new TypeCheckHints(type, profile, site.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints);
-        int hintsLength = hints.types.length;
-        if (hintsLength == 0) {
-            return new XirSnippet(materializeInstanceOfTemplates.get(site, 0), object, hub, trueValue, falseValue);
-        } else {
-            XirArgument[] params = new XirArgument[hintsLength + (hints.exact ? 3 : 4)];
-            int i = 0;
-            params[i++] = object;
-            if (!hints.exact) {
-                params[i++] = hub;
-            }
-            params[i++] = trueValue;
-            params[i++] = falseValue;
-            for (ResolvedJavaType hint : hints.types) {
-                params[i++] = XirArgument.forObject(((HotSpotJavaType) hint).klassOop());
-            }
-            XirTemplate template = hints.exact ? materializeInstanceOfTemplates.get(site, hintsLength, EXACT_HINTS) : materializeInstanceOfTemplates.get(site, hintsLength);
-            return new XirSnippet(template, params);
-        }
-    }
-
-    @Override
-    public XirSnippet genTypeBranch(XirSite site, XirArgument thisHub, XirArgument otherHub, JavaType type) {
-        assert type instanceof ResolvedJavaType;
-        return new XirSnippet(typeCheckTemplates.get(site), thisHub, otherHub);
-    }
-
-    @Override
-    public void initialize(CiXirAssembler asm) {
-        this.globalAsm = asm;
-    }
-
-    private void checkSubtype(CiXirAssembler asm, XirOperand result, XirOperand objHub, XirOperand hub) {
-        asm.push(objHub);
-        asm.push(hub);
-        asm.callRuntime(config.instanceofStub, null);
-        asm.pop(result);
-        asm.pop(result);
-    }
-
-    private static void useRegisters(CiXirAssembler asm, Register... registers) {
-        if (registers != null) {
-            for (Register register : registers) {
-                asm.createRegisterTemp("reg", Kind.Illegal, register);
-            }
-        }
-    }
-
-    public boolean is(TemplateFlag check, long flags) {
-        return (flags & check.bits()) == check.bits();
-    }
-
-    /**
-     * Base class for all the ondemand template generators. It is not normally subclassed directly, but through one of
-     * its subclasses (SimpleTemplates, KindTemplates, IndexTemplates).
-     */
-    private abstract class Templates {
-
-        private ConcurrentHashMap<Long, XirTemplate> templates = new ConcurrentHashMap<>();
-        private final long mask;
-
-        /**
-         * Each flag passed to this method will cause templates with and without it to be generated.
-         */
-        public Templates(TemplateFlag... flags) {
-            this.mask = getBits((int) INDEX_MASK, null, flags);
-        }
-
-        protected abstract XirTemplate create(CiXirAssembler asm, long flags);
-
-        protected long getBits(int index, XirSite site, TemplateFlag... flags) {
-            long bits = index;
-            if (site != null) {
-                bits |= site.requiresNullCheck() ? NULL_CHECK.bits() : 0;
-                bits |= site.requiresReadBarrier() ? READ_BARRIER.bits() : 0;
-                bits |= site.requiresWriteBarrier() ? WRITE_BARRIER.bits() : 0;
-                bits |= site.requiresArrayStoreCheck() ? STORE_CHECK.bits() : 0;
-                bits |= site.requiresBoundsCheck() ? BOUNDS_CHECK.bits() : 0;
-            }
-            if (flags != null) {
-                for (TemplateFlag flag : flags) {
-                    bits |= flag.bits();
-                }
-            }
-            return bits;
-        }
-
-        protected XirTemplate getInternal(long flags) {
-            long maskedFlags = flags & mask;
-            XirTemplate template = templates.get(maskedFlags);
-            if (template == null) {
-                template = create(HotSpotXirGenerator.this.globalAsm.copy(), maskedFlags);
-                templates.put(maskedFlags, template);
-            }
-            return template;
-        }
-    }
-
-    private abstract class SimpleTemplates extends Templates {
-
-        public SimpleTemplates(TemplateFlag... flags) {
-            super(flags);
-        }
-
-        public XirTemplate get(XirSite site, TemplateFlag... flags) {
-            return getInternal(getBits(0, site, flags));
-        }
-    }
-
-    private abstract class IndexTemplates extends Templates {
-
-        public IndexTemplates(TemplateFlag... flags) {
-            super(flags);
-        }
-
-        @Override
-        protected final XirTemplate create(CiXirAssembler asm, long flags) {
-            return create(asm, flags & FLAGS_MASK, (int) (flags & INDEX_MASK));
-        }
-
-        protected abstract XirTemplate create(CiXirAssembler asm, long flags, int index);
-
-        public XirTemplate get(XirSite site, int size, TemplateFlag... flags) {
-            return getInternal(getBits(size, site, flags));
-        }
-    }
-
-    private abstract class KindTemplates extends Templates {
-
-        public KindTemplates(TemplateFlag... flags) {
-            super(flags);
-        }
-
-        @Override
-        protected final XirTemplate create(CiXirAssembler asm, long flags) {
-            return create(asm, flags & FLAGS_MASK, Kind.VALUES[(int) (flags & INDEX_MASK)]);
-        }
-
-        protected abstract XirTemplate create(CiXirAssembler asm, long flags, Kind kind);
-
-        public XirTemplate get(XirSite site, Kind kind, TemplateFlag... flags) {
-            return getInternal(getBits(kind.ordinal(), site, flags));
-        }
-    }
-
-    private static void printCounter(PrintStream out, CheckcastCounter name, long count, long total) {
-        double percent = total == 0D ? 0D : ((double) (count * 100)) / total;
-        out.println(String.format("%16s: %5.2f%%%10d  // %s", name, percent, count, name.desc));
-    }
-
-    public static  void printCheckcastCounters(PrintStream out) {
-        class Count implements Comparable<Count> {
-            long c;
-            CheckcastCounter name;
-            Count(long c, CheckcastCounter name) {
-                this.c = c;
-                this.name = name;
-            }
-            public int compareTo(Count o) {
-                return (int) (o.c - c);
-            }
-        }
-
-        long total = 0;
-        Count[] counters = new Count[checkcastCounters.length];
-        for (int i = 0; i < counters.length; i++) {
-            counters[i] = new Count(checkcastCounters[i], CheckcastCounter.VALUES[i]);
-            total += checkcastCounters[i];
-        }
-        Arrays.sort(counters);
-
-        out.println();
-        out.println("** XIR checkcast counters **");
-        for (Count c : counters) {
-            printCounter(out, c.name, c.c, total);
-        }
-    }
-
-    public static void printCounters(PrintStream out) {
-        if (GraalOptions.CheckcastCounters) {
-            printCheckcastCounters(out);
-        }
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/TemplateFlag.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * 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.hotspot.meta;
-
-enum TemplateFlag {
-    NULL_CHECK,
-    READ_BARRIER,
-    WRITE_BARRIER,
-    STORE_CHECK,
-    BOUNDS_CHECK,
-    GIVEN_LENGTH,
-    INPUTS_DIFFERENT,
-    INPUTS_SAME,
-    STATIC_METHOD,
-    SYNCHRONIZED,
-    INTERFACE_TYPE,
-    NULL_TYPE,
-    EXACT_HINTS;
-
-    private static final long FIRST_FLAG = 0x0000000100000000L;
-    public static final long FLAGS_MASK = 0x0000FFFF00000000L;
-    public static final long INDEX_MASK = 0x00000000FFFFFFFFL;
-
-    public long bits() {
-        assert ((FIRST_FLAG << ordinal()) & FLAGS_MASK) != 0;
-        return FIRST_FLAG << ordinal();
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/RegisterNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/RegisterNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -22,10 +22,9 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-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.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -33,6 +32,7 @@
 /**
  * Access the value of a specific register.
  */
+@NodeInfo(nameTemplate = "Register %{p#register}")
 public final class RegisterNode extends FixedWithNextNode implements LIRLowerable {
 
     private final Register register;
@@ -65,13 +65,6 @@
         }
     }
 
-    @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> properties = super.getDebugProperties();
-        properties.put("register", register.toString());
-        return properties;
-    }
-
     @SuppressWarnings("unused")
     @NodeIntrinsic
     public static <T> T register(@ConstantNodeParameter Register register, @ConstantNodeParameter Kind kind) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import java.util.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -36,62 +34,31 @@
  */
 public final class TLABAllocateNode extends FixedWithNextNode implements Lowerable {
 
-    private final int size;
-    @Input private ValueNode sizeNode;
+    @Input private ValueNode size;
 
-    public TLABAllocateNode(int size, Kind wordKind) {
+    public TLABAllocateNode(ValueNode size, Kind wordKind) {
         super(StampFactory.forWord(wordKind, true));
         this.size = size;
-        this.sizeNode = null;
     }
 
-    public TLABAllocateNode(Kind wordKind, ValueNode size) {
-        super(StampFactory.forWord(wordKind, true));
-        this.size = -1;
-        this.sizeNode = size;
-    }
-
-    public boolean isSizeConstant() {
-        return sizeNode == null;
-    }
-
-    public int constantSize() {
-        assert isSizeConstant();
+    public ValueNode size() {
         return size;
     }
 
-    public ValueNode variableSize() {
-        assert !isSizeConstant();
-        return sizeNode;
-    }
-
     @Override
     public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
-    @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> debugProperties = super.getDebugProperties();
-        debugProperties.put("size", String.valueOf(size));
-        return debugProperties;
-    }
-
+    /**
+     * @return null if allocation fails
+     */
     /**
      * @return null if allocation fails
      */
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static Word allocateConstantSize(@ConstantNodeParameter int size, @ConstantNodeParameter Kind wordKind) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @return null if allocation fails
-     */
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static Word allocateVariableSize(@ConstantNodeParameter Kind wordKind, int size) {
+    public static Word allocateVariableSize(int size, @ConstantNodeParameter Kind wordKind) {
         throw new UnsupportedOperationException();
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Wed Jul 18 10:50:57 2012 -0700
@@ -52,7 +52,7 @@
         RegisterValue objectFixed = OBJECT.asValue(Kind.Object);
         gen.emitMove(gen.operand(object), objectFixed);
         LIRFrameState info = gen.state();
-        gen.append(new AMD64VerifyOopStubCallOp(gen.operand(object), info));
+        gen.append(new AMD64VerifyOopStubCallOp(objectFixed, info));
     }
 
     @SuppressWarnings("unused")
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java	Wed Jul 18 10:50:57 2012 -0700
@@ -30,6 +30,7 @@
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.Snippet.ConstantParameter;
 import com.oracle.graal.snippets.Snippet.Fold;
+import com.oracle.graal.snippets.nodes.*;
 
 
 @SuppressWarnings("unused")
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Wed Jul 18 10:50:57 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,15 +22,9 @@
  */
 package com.oracle.graal.hotspot.snippets;
 import static com.oracle.graal.hotspot.snippets.ArrayCopySnippets.*;
-import static com.oracle.graal.hotspot.snippets.CheckCastSnippets.Counter.*;
 import static com.oracle.graal.snippets.Snippet.Multiple.*;
 import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*;
 
-import java.io.*;
-import java.util.*;
-
-import sun.misc.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
@@ -224,54 +218,6 @@
         return false;
     }
 
-    /**
-     * Counters for the various code paths through a checkcast.
-     */
-    public enum Counter {
-        hintsHit("hit a hint type"),
-        exactHit("exact type test succeeded"),
-        exactMiss("exact type test failed"),
-        isNull("object tested was null"),
-        cacheHit("secondary type cache hit"),
-        secondariesHit("secondaries scan succeeded"),
-        secondariesMiss("secondaries scan failed"),
-        displayHit("primary type test succeeded"),
-        displayMiss("primary type test failed"),
-        T_equals_S("object type was equal to secondary type");
-
-        final String description;
-        final int index;
-        long count;
-
-        private Counter(String desc) {
-            this.description = desc;
-            this.index = ordinal();
-        }
-
-        @Fold
-        static int countOffset() {
-            try {
-                return (int) Unsafe.getUnsafe().objectFieldOffset(Counter.class.getDeclaredField("count"));
-            } catch (Exception e) {
-                throw new GraalInternalError(e);
-            }
-        }
-
-        /**
-         * Increments this counter if counters are enabled. The body of this method has been carefully crafted
-         * such that it contains no safepoints and no calls, neither of which are permissible in a snippet.
-         * Also, increments are not guaranteed to be atomic which is acceptable for a counter.
-         */
-        void inc() {
-            if (ENABLED) {
-                DirectObjectStoreNode.storeLong(this, countOffset(), 0, count + 1);
-            }
-        }
-
-        static final Counter[] VALUES = values();
-        static final boolean ENABLED = GraalOptions.CheckcastCounters;
-    }
-
     @Fold
     private static int superCheckOffsetOffset() {
         return HotSpotGraalRuntime.getInstance().getConfig().superCheckOffsetOffset;
@@ -292,41 +238,6 @@
         return HotSpotGraalRuntime.getInstance().getConfig().hubOffset;
     }
 
-    public static void printCounter(PrintStream out, Counter c, long total) {
-        double percent = total == 0D ? 0D : ((double) (c.count * 100)) / total;
-        out.println(String.format("%16s: %5.2f%%%10d  // %s", c.name(), percent, c.count, c.description));
-    }
-
-    public static void printCounters(PrintStream out) {
-        if (!Counter.ENABLED) {
-            return;
-        }
-        Counter[] counters = Counter.values();
-        Arrays.sort(counters, new Comparator<Counter>() {
-            @Override
-            public int compare(Counter o1, Counter o2) {
-                if (o1.count > o2.count) {
-                    return -1;
-                } else if (o2.count > o1.count) {
-                    return 1;
-                }
-                return 0;
-            }
-
-        });
-
-        long total = 0;
-        for (Counter c : counters) {
-            total += c.count;
-        }
-
-        out.println();
-        out.println("** Checkcast counters **");
-        for (Counter c : counters) {
-            printCounter(out, c, total);
-        }
-    }
-
     public static class Templates {
 
         private final Cache cache;
@@ -393,4 +304,16 @@
             return hintHubs;
         }
     }
+
+    private static final SnippetCounter.Group counters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Checkcast") : null;
+    private static final SnippetCounter hintsHit = new SnippetCounter(counters, "hintsHit", "hit a hint type");
+    private static final SnippetCounter exactHit = new SnippetCounter(counters, "exactHit", "exact type test succeeded");
+    private static final SnippetCounter exactMiss = new SnippetCounter(counters, "exactMiss", "exact type test failed");
+    private static final SnippetCounter isNull = new SnippetCounter(counters, "isNull", "object tested was null");
+    private static final SnippetCounter cacheHit = new SnippetCounter(counters, "cacheHit", "secondary type cache hit");
+    private static final SnippetCounter secondariesHit = new SnippetCounter(counters, "secondariesHit", "secondaries scan succeeded");
+    private static final SnippetCounter secondariesMiss = new SnippetCounter(counters, "secondariesMiss", "secondaries scan failed");
+    private static final SnippetCounter displayHit = new SnippetCounter(counters, "displayHit", "primary type test succeeded");
+    private static final SnippetCounter displayMiss = new SnippetCounter(counters, "displayMiss", "primary type test failed");
+    private static final SnippetCounter T_equals_S = new SnippetCounter(counters, "T_equals_S", "object type was equal to secondary type");
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectObjectStoreNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +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.hotspot.snippets;
-
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.snippets.*;
-
-/**
- * A special purpose store node that differs from {@link UnsafeStoreNode} in that
- * it is not a {@link StateSplit} and does not include a write barrier.
- */
-class DirectObjectStoreNode extends FixedWithNextNode implements Lowerable {
-    @Input private ValueNode object;
-    @Input private ValueNode value;
-    @Input private ValueNode offset;
-    private final int displacement;
-
-    public DirectObjectStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value) {
-        super(StampFactory.forVoid());
-        this.object = object;
-        this.value = value;
-        this.offset = offset;
-        this.displacement = displacement;
-    }
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static void storeObject(Object obj, @ConstantNodeParameter int displacement, long offset, Object value) {
-        throw new UnsupportedOperationException();
-    }
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static void storeLong(Object obj, @ConstantNodeParameter int displacement, long offset, long value) {
-        throw new UnsupportedOperationException();
-    }
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static void storeWord(Object obj, @ConstantNodeParameter int displacement, long offset, Word value) {
-        throw new UnsupportedOperationException();
-    }
-
-    @SuppressWarnings("unused")
-    @NodeIntrinsic
-    public static void storeInt(Object obj, @ConstantNodeParameter int displacement, long offset, int value) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void lower(LoweringTool tool) {
-        StructuredGraph graph = (StructuredGraph) this.graph();
-        IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, false);
-        WriteNode write = graph.add(new WriteNode(object, value, location));
-        graph.replaceFixedWithFixed(this, write);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Wed Jul 18 10:50:57 2012 -0700
@@ -24,15 +24,16 @@
 
 import static com.oracle.graal.hotspot.nodes.CastFromHub.*;
 import static com.oracle.graal.hotspot.nodes.RegisterNode.*;
-import static com.oracle.graal.hotspot.snippets.DirectObjectStoreNode.*;
 import static com.oracle.graal.nodes.extended.UnsafeLoadNode.*;
 import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*;
+import static com.oracle.graal.snippets.nodes.DirectObjectStoreNode.*;
 import static com.oracle.graal.snippets.nodes.ExplodeLoopNode.*;
 import static com.oracle.max.asm.target.amd64.AMD64.*;
 import static com.oracle.max.criutils.UnsignedMath.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
@@ -75,6 +76,7 @@
                     @ConstantParameter("size") int size) {
 
         if (memory == Word.zero()) {
+            new_stub.inc();
             return NewInstanceStubCall.call(hub);
         }
         formatObject(hub, size, memory, initialMarkWord);
@@ -106,8 +108,18 @@
 
     private static Object initializeArray(Word memory, Object hub, int length, int size, Word initialMarkWord, int headerSize, boolean isObjectArray) {
         if (memory == Word.zero()) {
+            if (isObjectArray) {
+                anewarray_stub.inc();
+            } else {
+                newarray_stub.inc();
+            }
             return NewArrayStubCall.call(isObjectArray, hub, length);
         }
+        if (isObjectArray) {
+            anewarray_loopInit.inc();
+        } else {
+            newarray_loopInit.inc();
+        }
         formatArray(hub, size, length, headerSize, memory, initialMarkWord);
         Object instance = memory.toObject();
         return castFromHub(verifyOop(instance), hub);
@@ -131,7 +143,7 @@
             DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.RuntimeConstraint);
         }
         int size = getArraySize(length, alignment, headerSize, log2ElementSize);
-        Word memory = TLABAllocateNode.allocateVariableSize(wordKind, size);
+        Word memory = TLABAllocateNode.allocateVariableSize(size, wordKind);
         return InitializeArrayNode.initialize(memory, length, size, type);
     }
 
@@ -171,11 +183,13 @@
         storeObject(memory, 0, markOffset(), headerPrototype);
         storeObject(memory, 0, hubOffset(), hub);
         if (size <= MAX_UNROLLED_OBJECT_ZEROING_SIZE) {
+            new_seqInit.inc();
             explodeLoop();
             for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
                 storeWord(memory, 0, offset, Word.zero());
             }
         } else {
+            new_loopInit.inc();
             for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) {
                 storeWord(memory, 0, offset, Word.zero());
             }
@@ -238,7 +252,8 @@
             if (!useTLAB) {
                 memory = ConstantNode.forConstant(new Constant(target.wordKind, 0L), runtime, graph);
             } else {
-                TLABAllocateNode tlabAllocateNode = graph.add(new TLABAllocateNode(size, wordKind()));
+                ConstantNode sizeNode = ConstantNode.forInt(size, graph);
+                TLABAllocateNode tlabAllocateNode = graph.add(new TLABAllocateNode(sizeNode, wordKind()));
                 graph.addBeforeFixed(newInstanceNode, tlabAllocateNode);
                 memory = tlabAllocateNode;
             }
@@ -272,7 +287,7 @@
                 // Calculate aligned size
                 int size = getArraySize(length, alignment, headerSize, log2ElementSize);
                 ConstantNode sizeNode = ConstantNode.forInt(size, graph);
-                tlabAllocateNode = graph.add(new TLABAllocateNode(size, target.wordKind));
+                tlabAllocateNode = graph.add(new TLABAllocateNode(sizeNode, target.wordKind));
                 graph.addBeforeFixed(newArrayNode, tlabAllocateNode);
                 InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(tlabAllocateNode, lengthNode, sizeNode, arrayType));
                 graph.replaceFixedWithFixed(newArrayNode, initializeNode);
@@ -293,12 +308,7 @@
         @SuppressWarnings("unused")
         public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) {
             StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph();
-            ValueNode size;
-            if (tlabAllocateNode.isSizeConstant()) {
-                size = ConstantNode.forInt(tlabAllocateNode.constantSize(), graph);
-            } else {
-                size = tlabAllocateNode.variableSize();
-            }
+            ValueNode size = tlabAllocateNode.size();
             Key key = new Key(allocate);
             Arguments arguments = arguments("size", size);
             SnippetTemplate template = cache.get(key);
@@ -380,4 +390,17 @@
     private static int arrayLengthOffset() {
         return HotSpotGraalRuntime.getInstance().getConfig().arrayLengthOffset;
     }
+
+    private static final SnippetCounter.Group countersNew = GraalOptions.SnippetCounters ? new SnippetCounter.Group("NewInstance") : null;
+    private static final SnippetCounter new_seqInit = new SnippetCounter(countersNew, "tlabSeqInit", "TLAB alloc with unrolled zeroing");
+    private static final SnippetCounter new_loopInit = new SnippetCounter(countersNew, "tlabLoopInit", "TLAB alloc with zeroing in a loop");
+    private static final SnippetCounter new_stub = new SnippetCounter(countersNew, "stub", "alloc and zeroing via stub");
+
+    private static final SnippetCounter.Group countersNewPrimitiveArray = GraalOptions.SnippetCounters ? new SnippetCounter.Group("NewPrimitiveArray") : null;
+    private static final SnippetCounter newarray_loopInit = new SnippetCounter(countersNewPrimitiveArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop");
+    private static final SnippetCounter newarray_stub = new SnippetCounter(countersNewPrimitiveArray, "stub", "alloc and zeroing via stub");
+
+    private static final SnippetCounter.Group countersNewObjectArray = GraalOptions.SnippetCounters ? new SnippetCounter.Group("NewObjectArray") : null;
+    private static final SnippetCounter anewarray_loopInit = new SnippetCounter(countersNewObjectArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop");
+    private static final SnippetCounter anewarray_stub = new SnippetCounter(countersNewObjectArray, "stub", "alloc and zeroing via stub");
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64DirectCallOp.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,105 @@
+/*
+ * 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.amd64;
+
+import static com.oracle.graal.hotspot.target.amd64.HotSpotAMD64Backend.*;
+import static com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind.*;
+
+import com.oracle.graal.api.code.CompilationResult.Mark;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+
+/**
+ * A direct call that complies with the conventions for such calls in HotSpot.
+ * In particular, for calls using an inline cache, a MOVE instruction is
+ * emitted just prior to the aligned direct call. This instruction
+ * (which moves null in RAX) is patched by the C++ Graal code to replace the
+ * null constant with Universe::non_oop_word(), a special sentinel
+ * used for the initial value of the klassOop in an inline cache.
+ * <p>
+ * For non-inline cache calls, a static call stub is emitted.
+ */
+@Opcode("CALL_DIRECT")
+final class AMD64DirectCallOp extends DirectCallOp {
+
+    /**
+     * The mark emitted at the position of the direct call instruction.
+     * This is only recorded for calls that have an associated static
+     * call stub (i.e., {@code invokeKind == Static || invokeKind == Special}).
+     */
+    Mark callsiteMark;
+
+    private final InvokeKind invokeKind;
+
+    AMD64DirectCallOp(Object targetMethod, Value result, Value[] parameters, LIRFrameState state, InvokeKind invokeKind, LIR lir) {
+        super(targetMethod, result, parameters, state, null);
+        this.invokeKind = invokeKind;
+
+        if (invokeKind == Static || invokeKind == Special) {
+            lir.stubs.add(new AMD64Code() {
+                public String description() {
+                    return "static call stub for Invoke" + AMD64DirectCallOp.this.invokeKind;
+                }
+                @Override
+                public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+                    assert callsiteMark != null : "static call site has not yet been emitted";
+                    tasm.recordMark(MARK_STATIC_CALL_STUB, callsiteMark);
+                    masm.movq(AMD64.rbx, 0L);
+                    Label dummy = new Label();
+                    masm.jmp(dummy);
+                    masm.bind(dummy);
+                }
+            });
+        }
+
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        if (invokeKind == Static || invokeKind == Special) {
+            tasm.recordMark(invokeKind == Static ? MARK_INVOKESTATIC : MARK_INVOKESPECIAL);
+        } else {
+            assert invokeKind == Virtual || invokeKind == Interface;
+            // The mark for an invocation that uses an inline cache must be placed at the instruction
+            // that loads the klassOop from the inline cache so that the C++ code can find it
+            // and replace the inline null value with Universe::non_oop_word()
+            tasm.recordMark(invokeKind == Virtual ? MARK_INVOKEVIRTUAL : MARK_INVOKEINTERFACE);
+            AMD64Move.move(tasm, masm, AMD64.rax.asValue(Kind.Object), Constant.NULL_OBJECT);
+        }
+
+        emitAlignmentForDirectCall(tasm, masm);
+
+        if (invokeKind == Static || invokeKind == Special) {
+            callsiteMark = tasm.recordMark(null);
+        }
+
+        AMD64Call.directCall(tasm, masm, targetMethod, state);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64IndirectCallOp.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,72 @@
+/*
+ * 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.amd64;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.hotspot.target.amd64.HotSpotAMD64Backend.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64Call.IndirectCallOp;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+
+/**
+ * A register indirect call that complies with the extra conventions for such calls in HotSpot.
+ * In particular, the methodOop of the callee must be in RBX for the case where a vtable entry's
+ * _from_compiled_entry is the address of an C2I adapter. Such adapters expect the target
+ * method to be in RBX.
+ */
+@Opcode("CALL_INDIRECT")
+final class AMD64IndirectCallOp extends IndirectCallOp {
+
+    /**
+     * Vtable stubs expect the methodOop in RBX.
+     */
+    public static final Register METHOD_OOP = AMD64.rbx;
+
+    @Use({REG}) protected Value methodOop;
+
+    AMD64IndirectCallOp(Object targetMethod, Value result, Value[] parameters, Value methodOop, Value targetAddress, LIRFrameState state) {
+        super(targetMethod, result, parameters, targetAddress, state, null);
+        this.methodOop = methodOop;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        tasm.recordMark(MARK_INLINE_INVOKEVIRTUAL);
+        Register callReg = asRegister(targetAddress);
+        assert callReg != METHOD_OOP;
+        AMD64Call.indirectCall(tasm, masm, callReg, targetMethod, state);
+    }
+
+    @Override
+    protected void verify() {
+        super.verify();
+        assert asRegister(methodOop) == METHOD_OOP;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64SafepointOp.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64SafepointOp.java	Wed Jul 18 10:50:57 2012 -0700
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.target.amd64;
 
-import static com.oracle.graal.hotspot.meta.HotSpotXirGenerator.*;
+import static com.oracle.graal.hotspot.target.amd64.HotSpotAMD64Backend.*;
 import static com.oracle.max.asm.target.amd64.AMD64.*;
 
 import com.oracle.graal.api.code.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TailcallOp.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TailcallOp.java	Wed Jul 18 10:50:57 2012 -0700
@@ -26,6 +26,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
@@ -33,7 +34,7 @@
 import com.oracle.max.asm.target.amd64.*;
 
 /**
- * Performs a hard-coded tail call to the specified target, which normally should be an RiCompiledCode instance.
+ * Performs a hard-coded tail call to the specified target, which normally should be an {@link InstalledCode} instance.
  */
 @Opcode("TAILCALL")
 public class AMD64TailcallOp extends AMD64LIRInstruction {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java	Wed Jul 18 10:50:57 2012 -0700
@@ -24,10 +24,11 @@
 
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.hotspot.meta.HotSpotXirGenerator.*;
+import static com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind.*;
 import static com.oracle.max.asm.target.amd64.AMD64.*;
 
 import java.lang.reflect.*;
+import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -44,45 +45,48 @@
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.cri.xir.*;
 
+/**
+ * HotSpot AMD64 specific backend.
+ */
 public class HotSpotAMD64Backend extends Backend {
 
+    // this needs to correspond to graal_CodeInstaller.hpp
+    // @formatter:off
+    public static final Integer MARK_VERIFIED_ENTRY            = 0x0001;
+    public static final Integer MARK_UNVERIFIED_ENTRY          = 0x0002;
+    public static final Integer MARK_OSR_ENTRY                 = 0x0003;
+    public static final Integer MARK_UNWIND_ENTRY              = 0x0004;
+    public static final Integer MARK_EXCEPTION_HANDLER_ENTRY   = 0x0005;
+    public static final Integer MARK_DEOPT_HANDLER_ENTRY       = 0x0006;
+
+    public static final Integer MARK_STATIC_CALL_STUB          = 0x1000;
+
+    public static final Integer MARK_INVOKEINTERFACE           = 0x2001;
+    public static final Integer MARK_INVOKESTATIC              = 0x2002;
+    public static final Integer MARK_INVOKESPECIAL             = 0x2003;
+    public static final Integer MARK_INVOKEVIRTUAL             = 0x2004;
+    public static final Integer MARK_INLINE_INVOKEVIRTUAL      = 0x2005;
+
+    public static final Integer MARK_IMPLICIT_NULL             = 0x3000;
+    public static final Integer MARK_POLL_NEAR                 = 0x3001;
+    public static final Integer MARK_POLL_RETURN_NEAR          = 0x3002;
+    public static final Integer MARK_POLL_FAR                  = 0x3003;
+    public static final Integer MARK_POLL_RETURN_FAR           = 0x3004;
+
+    // @formatter:on
     public HotSpotAMD64Backend(CodeCacheProvider runtime, TargetDescription target) {
         super(runtime, target);
     }
 
     @Override
-    public LIRGenerator newLIRGenerator(Graph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, RiXirGenerator xir, Assumptions assumptions) {
-        return new AMD64LIRGenerator(graph, runtime, target, frameMap, method, lir, xir, assumptions) {
-
-            @Override
-            public void visitSafepointNode(SafepointNode i) {
-                LIRFrameState info = state();
-                append(new AMD64SafepointOp(info, ((HotSpotRuntime) runtime).config));
-            }
-
-            @Override
-            public void visitExceptionObject(ExceptionObjectNode x) {
-                HotSpotVMConfig config = ((HotSpotRuntime) runtime).config;
-                RegisterValue thread = r15.asValue();
-                Address exceptionAddress = new Address(Kind.Object, thread, config.threadExceptionOopOffset);
-                Address pcAddress = new Address(Kind.Long, thread, config.threadExceptionPcOffset);
-                Value exception = emitLoad(exceptionAddress, false);
-                emitStore(exceptionAddress, Constant.NULL_OBJECT, false);
-                emitStore(pcAddress, Constant.LONG_0, false);
-                setResult(x, exception);
-            }
-
-            @Override
-            protected void emitPrologue() {
-                super.emitPrologue();
-                MethodEntryCounters.emitCounter(this, method);
-            }
-        };
+    public LIRGenerator newLIRGenerator(Graph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, XirGenerator xir, Assumptions assumptions) {
+        return new HotSpotAMD64LIRGenerator(graph, runtime, target, frameMap, method, lir, xir, assumptions);
     }
 
     @Override
@@ -90,6 +94,86 @@
         return new AMD64XirAssembler(target);
     }
 
+    static final class HotSpotAMD64LIRGenerator extends AMD64LIRGenerator {
+
+        private HotSpotAMD64LIRGenerator(Graph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, XirGenerator xir,
+                        Assumptions assumptions) {
+            super(graph, runtime, target, frameMap, method, lir, xir, assumptions);
+        }
+
+        @Override
+        public void visitSafepointNode(SafepointNode i) {
+            LIRFrameState info = state();
+            append(new AMD64SafepointOp(info, ((HotSpotRuntime) runtime).config));
+        }
+
+        @Override
+        public void visitExceptionObject(ExceptionObjectNode x) {
+            HotSpotVMConfig config = ((HotSpotRuntime) runtime).config;
+            RegisterValue thread = r15.asValue();
+            Address exceptionAddress = new Address(Kind.Object, thread, config.threadExceptionOopOffset);
+            Address pcAddress = new Address(Kind.Long, thread, config.threadExceptionPcOffset);
+            Value exception = emitLoad(exceptionAddress, false);
+            emitStore(exceptionAddress, Constant.NULL_OBJECT, false);
+            emitStore(pcAddress, Constant.LONG_0, false);
+            setResult(x, exception);
+        }
+
+        @Override
+        protected void emitPrologue() {
+            super.emitPrologue();
+            MethodEntryCounters.emitCounter(this, method);
+        }
+
+        @Override
+        public void emitInvoke(Invoke x) {
+            if (GraalOptions.XIRLowerInvokes) {
+                super.emitInvoke(x);
+                return;
+            }
+            final MethodCallTargetNode callTarget = x.callTarget();
+            final InvokeKind invokeKind = callTarget.invokeKind();
+            Kind[] signature = MetaUtil.signatureToKinds(callTarget.targetMethod().signature(), callTarget.isStatic() ? null : callTarget.targetMethod().holder().kind());
+            CallingConvention cc = frameMap.registerConfig.getCallingConvention(JavaCall, signature, target(), false);
+            frameMap.callsMethod(cc, JavaCall);
+
+            ValueNode methodOopNode = null;
+            boolean inlineVirtualCall = false;
+            if (callTarget.computedAddress() != null) {
+                // If a virtual dispatch address was computed, then an extra argument
+                // was append for passing the methodOop in RBX
+                methodOopNode = callTarget.arguments().remove(callTarget.arguments().size() - 1);
+
+                if (invokeKind == Virtual) {
+                    inlineVirtualCall = true;
+                } else {
+                    // An invokevirtual may have been canonicalized into an invokespecial;
+                    // the methodOop argument is ignored in this case
+                    methodOopNode = null;
+                }
+            }
+
+            List<Value> argList = visitInvokeArguments(cc, callTarget.arguments());
+            Value[] parameters = argList.toArray(new Value[argList.size()]);
+
+            LIRFrameState callState = stateFor(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null, x.leafGraphId());
+            Value result = resultOperandFor(x.node().kind());
+            if (!inlineVirtualCall) {
+                assert methodOopNode == null;
+                append(new AMD64DirectCallOp(callTarget.targetMethod(), result, parameters, callState, invokeKind, lir));
+            } else {
+                assert methodOopNode != null;
+                Value methodOop = AMD64.rbx.asValue();
+                emitMove(operand(methodOopNode), methodOop);
+                append(new AMD64IndirectCallOp(callTarget.targetMethod(), result, parameters, methodOop, operand(callTarget.computedAddress()), callState));
+            }
+
+            if (isLegal(result)) {
+                setResult(x.node(), emitMove(result));
+            }
+        }
+    }
+
     class HotSpotFrameContext implements FrameContext {
 
         @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotXirGenerator.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.target.amd64;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.hotspot.target.amd64.TemplateFlag.*;
+import static com.oracle.graal.hotspot.target.amd64.HotSpotAMD64Backend.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.Address.*;
+import com.oracle.graal.api.code.Register.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.cri.xir.*;
+import com.oracle.max.cri.xir.XirAssembler.XirConstant;
+import com.oracle.max.cri.xir.XirAssembler.XirLabel;
+import com.oracle.max.cri.xir.XirAssembler.XirMark;
+import com.oracle.max.cri.xir.XirAssembler.XirOperand;
+import com.oracle.max.cri.xir.XirAssembler.XirParameter;
+
+public class HotSpotXirGenerator implements XirGenerator {
+
+    private final HotSpotVMConfig config;
+    private final TargetDescription target;
+    private final RegisterConfig registerConfig;
+    private final HotSpotGraalRuntime compiler;
+
+
+    private XirAssembler globalAsm;
+
+    public HotSpotXirGenerator(HotSpotVMConfig config, TargetDescription target, RegisterConfig registerConfig, HotSpotGraalRuntime compiler) {
+        this.config = config;
+        this.target = target;
+        this.registerConfig = registerConfig;
+        this.compiler = compiler;
+    }
+
+    private XirConstant wordConst(XirAssembler asm, long value) {
+        if (target.wordKind == Kind.Long) {
+            return asm.createConstant(Constant.forLong(value));
+        } else {
+            assert target.wordKind == Kind.Int;
+            return asm.createConstant(Constant.forInt((int) value));
+        }
+    }
+
+    private XirArgument wordArg(long value) {
+        if (target.wordKind == Kind.Long) {
+            return XirArgument.forLong(value);
+        } else {
+            assert target.wordKind == Kind.Int;
+            return XirArgument.forInt((int) value);
+        }
+    }
+
+    private SimpleTemplates invokeInterfaceTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(XirAssembler asm, long flags) {
+            asm.restart();
+            XirParameter receiver = asm.createInputParameter("receiver", Kind.Object);
+            XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind);
+            XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
+            XirOperand tempO = asm.createRegister("tempO", Kind.Object, AMD64.rax);
+
+            if (is(NULL_CHECK, flags)) {
+                asm.mark(MARK_IMPLICIT_NULL);
+                asm.pload(target.wordKind, temp, receiver, true);
+            }
+            asm.mark(MARK_INVOKEINTERFACE);
+            // Initialize the klassOop slot of an inline cache with null - the C++ Graal code will convert this to Universe::non_oop_word()
+            asm.mov(tempO, asm.createConstant(Constant.NULL_OBJECT));
+
+            return asm.finishTemplate(addr, "invokeinterface");
+        }
+    };
+
+    private SimpleTemplates invokeVirtualTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(XirAssembler asm, long flags) {
+            asm.restart();
+            XirParameter receiver = asm.createInputParameter("receiver", Kind.Object);
+            XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind);
+            XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
+            XirOperand tempO = asm.createRegister("tempO", Kind.Object, AMD64.rax);
+
+            if (is(NULL_CHECK, flags)) {
+                asm.mark(MARK_IMPLICIT_NULL);
+                asm.pload(target.wordKind, temp, receiver, true);
+            }
+            asm.mark(MARK_INVOKEVIRTUAL);
+            // Initialize the klassOop slot of an inline cache with null - the C++ Graal code will convert this to Universe::non_oop_word()
+            asm.mov(tempO, asm.createConstant(Constant.NULL_OBJECT));
+
+            return asm.finishTemplate(addr, "invokevirtual");
+        }
+    };
+
+    private IndexTemplates inlinedInvokeVirtualTemplates = new IndexTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(XirAssembler asm, long flags, int vtableEntryOffset) {
+            asm.restart();
+            XirParameter receiver = asm.createInputParameter("receiver", Kind.Object);
+            XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
+            XirOperand method = asm.createRegisterTemp("method", Kind.Object, AMD64.rbx);
+
+            // load class from receiver
+            if (is(NULL_CHECK, flags)) {
+                asm.mark(MARK_IMPLICIT_NULL);
+            }
+            asm.pload(target.wordKind, temp, receiver, asm.i(config.hubOffset), true);
+            // load vtable entry
+            asm.pload(target.wordKind, method, temp, asm.i(vtableEntryOffset), false);
+            // load entry point from methodOop
+            asm.mark(MARK_IMPLICIT_NULL);
+            asm.pload(target.wordKind, temp, method, asm.i(config.methodCompiledEntryOffset), true);
+            asm.mark(MARK_INLINE_INVOKEVIRTUAL);
+
+            return asm.finishTemplate(temp, "invokevirtual");
+        }
+    };
+
+    private SimpleTemplates invokeSpecialTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(XirAssembler asm, long flags) {
+            asm.restart();
+            XirParameter receiver = asm.createInputParameter("receiver", Kind.Object);
+            XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind);
+            XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax);
+            XirLabel stub = asm.createOutOfLineLabel("call stub");
+
+            if (is(NULL_CHECK, flags)) {
+                asm.mark(MARK_IMPLICIT_NULL);
+                asm.pload(target.wordKind, temp, receiver, true);
+            }
+            asm.mark(MARK_INVOKESPECIAL);
+
+            // -- out of line -------------------------------------------------------
+            asm.bindOutOfLine(stub);
+            XirOperand method = asm.createRegisterTemp("method", target.wordKind, AMD64.rbx);
+            asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE);
+            asm.mov(method, wordConst(asm, 0));
+            XirLabel dummy = asm.createOutOfLineLabel("dummy");
+            asm.jmp(dummy);
+            asm.bindOutOfLine(dummy);
+
+            return asm.finishTemplate(addr, "invokespecial");
+        }
+    };
+
+    private SimpleTemplates invokeStaticTemplates = new SimpleTemplates() {
+
+        @Override
+        protected XirTemplate create(XirAssembler asm, long flags) {
+            asm.restart();
+            XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind);
+
+            XirLabel stub = asm.createOutOfLineLabel("call stub");
+            asm.mark(MARK_INVOKESTATIC);
+
+            // -- out of line -------------------------------------------------------
+            asm.bindOutOfLine(stub);
+            XirOperand method = asm.createRegisterTemp("method", target.wordKind, AMD64.rbx);
+            asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE);
+            asm.mov(method, wordConst(asm, 0));
+            XirLabel dummy = asm.createOutOfLineLabel("dummy");
+            asm.jmp(dummy);
+            asm.bindOutOfLine(dummy);
+
+            return asm.finishTemplate(addr, "invokestatic");
+        }
+    };
+
+    private SimpleTemplates monitorEnterTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(XirAssembler asm, long flags) {
+            asm.restart(Kind.Void);
+            XirParameter object = asm.createInputParameter("object", Kind.Object);
+            XirParameter lock = asm.createInputParameter("lock", target.wordKind);
+
+            if (is(NULL_CHECK, flags)) {
+                asm.mark(MARK_IMPLICIT_NULL);
+                asm.pload(target.wordKind, asm.createTemp("temp", target.wordKind), object, true);
+            }
+
+
+            // (thomaswue) It is important to use for this runtime call the debug info AFTER the monitor enter. Otherwise the monitor object
+            // is not correctly garbage collected.
+            final boolean useInfoAfter = true;
+
+            if (config.useFastLocking) {
+                useRegisters(asm, AMD64.rax, AMD64.rbx);
+                useRegisters(asm, getGeneralParameterRegister(0));
+                useRegisters(asm, getGeneralParameterRegister(1));
+                asm.callRuntime(config.fastMonitorEnterStub, null, useInfoAfter, object, lock);
+            } else {
+                asm.reserveOutgoingStack(target.wordSize * 2);
+                XirOperand rsp = asm.createRegister("rsp", target.wordKind, asRegister(AMD64.RSP));
+                asm.pstore(Kind.Object, rsp, asm.i(target.wordSize), object, false);
+                asm.pstore(target.wordKind, rsp, asm.i(0), lock, false);
+                asm.callRuntime(config.monitorEnterStub, null, useInfoAfter);
+            }
+
+            return asm.finishTemplate("monitorEnter");
+        }
+    };
+
+    private Register getGeneralParameterRegister(int index) {
+        return registerConfig.getCallingConventionRegisters(CallingConvention.Type.RuntimeCall, RegisterFlag.CPU)[index];
+    }
+
+    private SimpleTemplates monitorExitTemplates = new SimpleTemplates(NULL_CHECK) {
+
+        @Override
+        protected XirTemplate create(XirAssembler asm, long flags) {
+            asm.restart(Kind.Void);
+            XirParameter object = asm.createInputParameter("object", Kind.Object);
+            XirParameter lock = asm.createInputParameter("lock", target.wordKind);
+
+            if (config.useFastLocking) {
+                useRegisters(asm, AMD64.rax, AMD64.rbx);
+                useRegisters(asm, getGeneralParameterRegister(0));
+                useRegisters(asm, getGeneralParameterRegister(1));
+                asm.callRuntime(config.fastMonitorExitStub, null, object, lock);
+            } else {
+                asm.reserveOutgoingStack(target.wordSize);
+                asm.pstore(target.wordKind, asm.createRegister("rsp", target.wordKind, asRegister(AMD64.RSP)), asm.i(0), lock, false);
+                asm.callRuntime(config.monitorExitStub, null);
+            }
+
+            return asm.finishTemplate("monitorExit");
+        }
+    };
+
+    private final IndexTemplates newInstanceTemplates = new IndexTemplates() {
+
+        @Override
+        protected XirTemplate create(XirAssembler asm, long flags, int size) {
+            XirOperand result = asm.restart(target.wordKind);
+            XirOperand hub = asm.createInputParameter("hub", Kind.Object);
+
+            XirOperand temp1 = asm.createRegisterTemp("temp1", target.wordKind, AMD64.rcx);
+            XirOperand temp1o = asm.createRegister("temp1o", Kind.Object, AMD64.rcx);
+            XirOperand temp2 = asm.createRegisterTemp("temp2", target.wordKind, AMD64.rbx);
+            XirOperand temp2i = asm.createRegister("temp2i", Kind.Int, AMD64.rbx);
+            useRegisters(asm, AMD64.rsi);
+            XirLabel tlabFull = asm.createOutOfLineLabel("tlab full");
+            XirLabel resume = asm.createInlineLabel("resume");
+
+            // check if the class is already initialized
+            asm.pload(Kind.Int, temp2i, hub, asm.i(config.klassStateOffset), false);
+            asm.jneq(tlabFull, temp2i, asm.i(config.klassStateFullyInitialized));
+
+            XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15);
+            asm.pload(target.wordKind, result, thread, asm.i(config.threadTlabTopOffset), false);
+            asm.add(temp1, result, wordConst(asm, size));
+            asm.pload(target.wordKind, temp2, thread, asm.i(config.threadTlabEndOffset), false);
+
+            asm.jgt(tlabFull, temp1, temp2);
+            asm.pstore(target.wordKind, thread, asm.i(config.threadTlabTopOffset), temp1, false);
+
+            asm.bindInline(resume);
+
+            asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false);
+            asm.pstore(target.wordKind, result, asm.i(config.markOffset), temp1, false);
+            asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory
+            asm.pstore(Kind.Object, result, asm.i(config.hubOffset), temp1o, false);
+
+            if (size > 2 * target.wordSize) {
+                asm.mov(temp1, wordConst(asm, 0));
+                for (int offset = 2 * target.wordSize; offset < size; offset += target.wordSize) {
+                    asm.pstore(target.wordKind, result, asm.i(offset), temp1, false);
+                }
+            }
+
+            // -- out of line -------------------------------------------------------
+            asm.bindOutOfLine(tlabFull);
+            XirOperand arg = asm.createRegisterTemp("runtime call argument", Kind.Object, AMD64.rdx);
+            asm.mov(arg, hub);
+            useRegisters(asm, AMD64.rax);
+            asm.callRuntime(config.newInstanceStub, result);
+            asm.jmp(resume);
+
+            return asm.finishTemplate("new instance");
+        }
+    };
+
+    private SimpleTemplates newObjectArrayTemplates = new SimpleTemplates() {
+
+        @Override
+        protected XirTemplate create(XirAssembler asm, long flags) {
+            emitNewTypeArray(asm, Kind.Object, config.useFastNewObjectArray, config.newObjectArrayStub);
+            return asm.finishTemplate("newObjectArray");
+        }
+    };
+
+    private void emitNewTypeArray(XirAssembler asm, Kind kind, boolean useFast, long slowPathStub) {
+        XirOperand result = asm.restart(target.wordKind);
+
+        XirParameter lengthParam = asm.createInputParameter("length", Kind.Int, true);
+
+        XirOperand length = asm.createRegisterTemp("length", Kind.Int, AMD64.rbx);
+        XirOperand hub = asm.createRegisterTemp("hub", Kind.Object, AMD64.rdx);
+
+        // Registers rsi, rcx, rdi, and rax are needed by the runtime call.
+        // Hub needs to be on rdx, length on rbx.
+        XirOperand temp1 = asm.createRegisterTemp("temp1", target.wordKind, AMD64.rcx);
+        XirOperand temp1o = asm.createRegister("temp1o", Kind.Object, AMD64.rcx);
+        XirOperand temp2 = asm.createRegisterTemp("temp2", target.wordKind, AMD64.rax);
+        XirOperand temp3 = asm.createRegisterTemp("temp3", target.wordKind, AMD64.rdi);
+        XirOperand size = asm.createRegisterTemp("size", Kind.Int, AMD64.rsi);
+
+        asm.mov(hub, asm.createConstantInputParameter("hub", Kind.Object));
+        asm.mov(length, lengthParam);
+
+        if (useFast) {
+
+            XirLabel slowPath = asm.createOutOfLineLabel("slowPath");
+
+            XirLabel done = asm.createInlineLabel("done");
+
+            // Check for negative array size.
+            // TODO: Also check for upper bound
+            asm.jlt(slowPath, length, asm.i(0));
+
+            final int aligning = target.wordSize;
+            final int arrayLengthOffset = target.wordSize * 2;
+            final int arrayElementOffset = kind.arrayBaseOffset();
+
+            // Calculate aligned size
+            asm.mov(size, length);
+            int scale = CodeUtil.log2(target.sizeInBytes(kind));
+            if (scale != 0) {
+                asm.shl(size, size, asm.i(scale));
+            }
+            asm.add(size, size, asm.i(arrayElementOffset + aligning - 1));
+            long mask = 0xFFFFFFFFL;
+            mask <<= CodeUtil.log2(aligning);
+            asm.and(size, size, asm.i((int) mask));
+
+            // Try tlab allocation
+            XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15);
+            asm.pload(target.wordKind, result, thread, asm.i(config.threadTlabTopOffset), false);
+            asm.add(temp1, result, size);
+            asm.pload(target.wordKind, temp2, thread, asm.i(config.threadTlabEndOffset), false);
+            asm.jgt(slowPath, temp1, temp2);
+            asm.pstore(target.wordKind, thread, asm.i(config.threadTlabTopOffset), temp1, false);
+
+            // Now the new object is in result, store mark word and klass
+            asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false);
+            asm.pstore(target.wordKind, result, asm.i(config.markOffset), temp1, false);
+            asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory
+            asm.pstore(Kind.Object, result, asm.i(config.hubOffset), temp1o, false);
+
+            // Store array length
+            asm.pstore(Kind.Int, result, asm.i(arrayLengthOffset), length, false);
+
+            // Initialize with 0
+            XirLabel top = asm.createInlineLabel("top");
+            asm.sub(size, size, asm.i(arrayElementOffset));
+            asm.shr(size, size, asm.i(Scale.Times8.log2));
+            asm.jeq(done, size, asm.i(0));
+            asm.xor(temp3, temp3, temp3);
+            asm.bindInline(top);
+            asm.pstore(target.wordKind, result, size, temp3, arrayElementOffset - target.wordSize, Scale.Times8, false);
+            asm.decAndJumpNotZero(top, size);
+
+            asm.bindInline(done);
+
+            // Slow path
+            asm.bindOutOfLine(slowPath);
+            asm.callRuntime(slowPathStub, result);
+            asm.jmp(done);
+        } else {
+            asm.callRuntime(slowPathStub, result);
+        }
+    }
+
+    private KindTemplates newTypeArrayTemplates = new KindTemplates() {
+        @Override
+        protected XirTemplate create(XirAssembler asm, long flags, Kind kind) {
+            emitNewTypeArray(asm, kind, config.useFastNewTypeArray, config.newTypeArrayStub);
+            return asm.finishTemplate("newTypeArray<" + kind.toString() + ">");
+        }
+    };
+
+    private final IndexTemplates multiNewArrayTemplate = new IndexTemplates() {
+
+        @Override
+        protected XirTemplate create(XirAssembler asm, long flags, int dimensions) {
+            XirOperand result = asm.restart(Kind.Object);
+
+            XirOperand hub = asm.createRegisterTemp("hub", Kind.Object, AMD64.rax);
+            XirOperand rank = asm.createRegisterTemp("rank", Kind.Int, AMD64.rbx);
+            XirOperand sizes = asm.createRegisterTemp("sizes", Kind.Long, AMD64.rcx);
+            XirOperand thread = asm.createRegisterTemp("thread", Kind.Long, AMD64.r15);
+            asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorageOffset));
+            for (int i = 0; i < dimensions; i++) {
+                XirParameter length = asm.createInputParameter("length" + i, Kind.Int, true);
+                asm.pstore(Kind.Int, sizes, asm.i(i * target.sizeInBytes(Kind.Int)), length, false);
+            }
+
+            asm.mov(hub, asm.createConstantInputParameter("hub", Kind.Object));
+
+            asm.mov(rank, asm.i(dimensions));
+            // not necessary because we already have a temp in rax:  useRegisters(asm, AMD64.rax);
+            asm.callRuntime(config.newMultiArrayStub, result);
+            return asm.finishTemplate("multiNewArray" + dimensions);
+        }
+    };
+
+    enum CheckcastCounter {
+        hintsHit("hit a hint type"),
+        hintsMissed("missed the hint types"),
+        exact("tested type is (statically) final"),
+        noHints_class("profile information is not used (test type is a class)"),
+        noHints_iface("profile information is not used (test type is an interface)"),
+        noHints_unknown("test type is not a compile-time constant"),
+        isNull("object tested is null"),
+        exception("type test failed with a ClassCastException");
+
+        public final String desc;
+
+        private CheckcastCounter(String desc) {
+            this.desc = desc;
+        }
+
+        static final CheckcastCounter[] VALUES = values();
+    }
+
+    private static final long[] checkcastCounters = new long[CheckcastCounter.VALUES.length];
+
+    private IndexTemplates checkCastTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) {
+
+        private void incCounter(XirAssembler asm, XirOperand counter, XirParameter counters, CheckcastCounter offset) {
+            int disp = Unsafe.getUnsafe().arrayBaseOffset(long[].class);
+            Scale scale = Scale.fromInt(Unsafe.getUnsafe().arrayIndexScale(long[].class));
+            XirConstant index = asm.i(offset.ordinal());
+            asm.pload(Kind.Long, counter, counters, index, disp, scale, false);
+            asm.add(counter, counter, asm.i(1));
+            asm.pstore(Kind.Long, counters, index, counter, disp, scale, false);
+        }
+
+        @Override
+        protected XirTemplate create(XirAssembler asm, long flags, int hintCount) {
+            asm.restart(Kind.Void);
+            boolean exact = is(EXACT_HINTS, flags);
+            XirParameter counters = GraalOptions.SnippetCounters ? asm.createConstantInputParameter("counters", Kind.Object) : null;
+            XirParameter object = asm.createInputParameter("object", Kind.Object);
+            final XirOperand hub = exact ? null : asm.createConstantInputParameter("hub", Kind.Object);
+
+            XirOperand objHub = asm.createTemp("objHub", Kind.Object);
+            XirOperand counter = counters != null ? asm.createTemp("counter", Kind.Long) : null;
+
+            XirLabel success = asm.createInlineLabel("success");
+            XirLabel slowPath = asm.createOutOfLineLabel("slow path");
+
+            if (is(NULL_CHECK, flags)) {
+                // null can be cast to anything
+                if (counters != null) {
+                    XirLabel isNotNull = asm.createInlineLabel("isNull");
+                    asm.jneq(isNotNull, object, asm.o(null));
+                    incCounter(asm, counter, counters, CheckcastCounter.isNull);
+                    asm.jmp(success);
+                    asm.bindInline(isNotNull);
+                } else {
+                    asm.jeq(success, object, asm.o(null));
+                }
+
+            }
+
+            asm.pload(Kind.Object, objHub, object, asm.i(config.hubOffset), false);
+            if (hintCount == 0) {
+                assert !exact;
+                if (counters != null) {
+                    CheckcastCounter cc;
+                    if (is(NULL_TYPE, flags)) {
+                        cc = CheckcastCounter.noHints_unknown;
+                    } else if (is(INTERFACE_TYPE, flags)) {
+                        cc = CheckcastCounter.noHints_iface;
+                    } else {
+                        cc = CheckcastCounter.noHints_class;
+                    }
+                    incCounter(asm, counter, counters, cc);
+                }
+
+                checkSubtype(asm, objHub, objHub, hub);
+                asm.jeq(slowPath, objHub, asm.o(null));
+                asm.bindInline(success);
+
+                // -- out of line -------------------------------------------------------
+                asm.bindOutOfLine(slowPath);
+            } else {
+                XirLabel hintsSuccess = counters == null ? success : asm.createInlineLabel("hintsSuccess");
+                XirOperand scratchObject = asm.createRegisterTemp("scratch", Kind.Object, AMD64.r10);
+                // if we get an exact match: succeed immediately
+                for (int i = 0; i < hintCount; i++) {
+                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, Kind.Object);
+                    asm.mov(scratchObject, hintHub);
+                    if (i < hintCount - 1) {
+                        asm.jeq(hintsSuccess, objHub, scratchObject);
+                    } else {
+                        asm.jneq(slowPath, objHub, scratchObject);
+                    }
+                }
+
+                if (counters != null) {
+                    asm.bindInline(hintsSuccess);
+                    incCounter(asm, counter, counters, exact ? CheckcastCounter.exact : CheckcastCounter.hintsHit);
+                }
+
+                asm.bindInline(success);
+
+                // -- out of line -------------------------------------------------------
+                asm.bindOutOfLine(slowPath);
+                if (!exact) {
+                    if (counters != null) {
+                        incCounter(asm, counter, counters, CheckcastCounter.hintsMissed);
+                    }
+                    checkSubtype(asm, objHub, objHub, hub);
+                    asm.jneq(success, objHub, asm.o(null));
+                }
+            }
+
+            if (counters != null) {
+                incCounter(asm, counter, counters, CheckcastCounter.exception);
+            }
+            DeoptimizationReason deoptReason = exact ? DeoptimizationReason.OptimizedTypeCheckViolated : DeoptimizationReason.ClassCastException;
+            XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10);
+            asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(DeoptimizationAction.InvalidateReprofile, deoptReason)));
+            asm.callRuntime(RuntimeCall.Deoptimize, null);
+            asm.shouldNotReachHere();
+
+            return asm.finishTemplate("checkcast");
+        }
+    };
+
+    private IndexTemplates instanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) {
+
+        @Override
+        protected XirTemplate create(XirAssembler asm, long flags, int hintCount) {
+            asm.restart(Kind.Void);
+            XirParameter object = asm.createInputParameter("object", Kind.Object);
+            final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", Kind.Object);
+
+            XirOperand objHub = asm.createTemp("objHub", Kind.Object);
+
+            XirLabel trueSucc = asm.createInlineLabel(XirLabel.TrueSuccessor);
+            XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor);
+
+            if (is(NULL_CHECK, flags)) {
+                // null isn't "instanceof" anything
+                asm.jeq(falseSucc, object, asm.o(null));
+            }
+
+            asm.pload(Kind.Object, objHub, object, asm.i(config.hubOffset), false);
+            if (hintCount == 0) {
+                assert !is(EXACT_HINTS, flags);
+                checkSubtype(asm, objHub, objHub, hub);
+                asm.jeq(falseSucc, objHub, asm.o(null));
+                asm.jmp(trueSucc);
+            } else {
+                XirLabel slowPath = null;
+                XirOperand scratchObject = asm.createRegisterTemp("scratch", Kind.Object, AMD64.r10);
+
+                // if we get an exact match: succeed immediately
+                for (int i = 0; i < hintCount; i++) {
+                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, Kind.Object);
+                    asm.mov(scratchObject, hintHub);
+                    if (i < hintCount - 1) {
+                        asm.jeq(trueSucc, objHub, scratchObject);
+                    } else {
+                        if (is(EXACT_HINTS, flags)) {
+                            asm.jneq(falseSucc, objHub, scratchObject);
+                            asm.jmp(trueSucc);
+                        } else {
+                            slowPath = asm.createOutOfLineLabel("slow path");
+                            asm.jneq(slowPath, objHub, scratchObject);
+                            asm.jmp(trueSucc);
+                        }
+                    }
+                }
+
+                // -- out of line -------------------------------------------------------
+                if (slowPath != null) {
+                    asm.bindOutOfLine(slowPath);
+                    checkSubtype(asm, objHub, objHub, hub);
+                    asm.jeq(falseSucc, objHub, asm.o(null));
+                    asm.jmp(trueSucc);
+                }
+            }
+
+            return asm.finishTemplate("instanceof");
+        }
+    };
+
+    private IndexTemplates materializeInstanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) {
+
+        @Override
+        protected XirTemplate create(XirAssembler asm, long flags, int hintCount) {
+            XirOperand result = asm.restart(Kind.Int);
+            XirParameter object = asm.createInputParameter("object", Kind.Object);
+            final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", Kind.Object);
+            XirOperand trueValue = asm.createInputParameter("trueValue", Kind.Int);
+            XirOperand falseValue = asm.createInputParameter("falseValue", Kind.Int);
+
+            XirOperand objHub = asm.createTemp("objHub", Kind.Object);
+
+            XirLabel end = asm.createInlineLabel("end");
+            XirLabel falseSucc = asm.createInlineLabel("ko");
+
+            if (is(NULL_CHECK, flags)) {
+                // null isn't "instanceof" anything
+                asm.jeq(falseSucc, object, asm.o(null));
+            }
+
+            asm.pload(Kind.Object, objHub, object, asm.i(config.hubOffset), false);
+            asm.mov(result, trueValue);
+
+            if (hintCount == 0) {
+                assert !is(EXACT_HINTS, flags);
+                checkSubtype(asm, objHub, objHub, hub);
+                asm.jneq(end, objHub, asm.o(null));
+                asm.bindInline(falseSucc);
+                asm.mov(result, falseValue);
+                asm.bindInline(end);
+            } else {
+                XirLabel slowPath = null;
+                XirOperand scratchObject = asm.createRegisterTemp("scratch", Kind.Object, AMD64.r10);
+
+                // if we get an exact match: succeed immediately
+                for (int i = 0; i < hintCount; i++) {
+                    XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, Kind.Object);
+                    asm.mov(scratchObject, hintHub);
+                    if (i < hintCount - 1) {
+                        asm.jeq(end, objHub, scratchObject);
+                    } else {
+                        if (is(EXACT_HINTS, flags)) {
+                            asm.jeq(end, objHub, scratchObject);
+                        } else {
+                            slowPath = asm.createOutOfLineLabel("slow path");
+                            asm.jeq(end, objHub, scratchObject);
+                            asm.jmp(slowPath);
+                        }
+                    }
+                }
+                asm.bindInline(falseSucc);
+                asm.mov(result, falseValue);
+                asm.bindInline(end);
+
+                // -- out of line -------------------------------------------------------
+                if (slowPath != null) {
+                    asm.bindOutOfLine(slowPath);
+                    checkSubtype(asm, objHub, objHub, hub);
+                    asm.jeq(falseSucc, objHub, asm.o(null));
+                    asm.jmp(end);
+                }
+            }
+
+            return asm.finishTemplate("instanceof");
+        }
+    };
+
+    private SimpleTemplates typeCheckTemplates = new SimpleTemplates(NULL_CHECK) {
+       @Override
+       protected XirTemplate create(XirAssembler asm, long flags) {
+           asm.restart(Kind.Void);
+           XirParameter objHub = asm.createInputParameter("objectHub", Kind.Object);
+           XirOperand hub = asm.createConstantInputParameter("hub", Kind.Object);
+           XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor);
+
+           XirOperand checkHub = asm.createTemp("checkHub", Kind.Object);
+
+           if (is(NULL_CHECK, flags)) {
+               asm.mark(MARK_IMPLICIT_NULL);
+           }
+
+           asm.mov(checkHub, hub);
+           // if we get an exact match: continue.
+           asm.jneq(falseSucc, objHub, checkHub);
+
+           return asm.finishTemplate("typeCheck");
+       }
+    };
+
+    @Override
+    public XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, JavaMethod method) {
+        return new XirSnippet(invokeInterfaceTemplates.get(site), receiver, wordArg(0));
+    }
+
+    @Override
+    public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, JavaMethod method, boolean megamorph) {
+        int vtableEntryOffset = 0;
+
+        if (GraalOptions.InlineVTableStubs && (GraalOptions.AlwaysInlineVTableStubs || megamorph)) {
+            HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
+            if (!hsMethod.holder().isInterface()) {
+                vtableEntryOffset = hsMethod.vtableEntryOffset();
+            }
+        }
+        if (vtableEntryOffset > 0) {
+            return new XirSnippet(inlinedInvokeVirtualTemplates.get(site, vtableEntryOffset), receiver);
+        } else {
+            return new XirSnippet(invokeVirtualTemplates.get(site), receiver, wordArg(0));
+        }
+    }
+
+    @Override
+    public XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, JavaMethod method) {
+        return new XirSnippet(invokeSpecialTemplates.get(site), receiver, wordArg(0));
+    }
+
+    @Override
+    public XirSnippet genInvokeStatic(XirSite site, JavaMethod method) {
+        return new XirSnippet(invokeStaticTemplates.get(site), wordArg(0));
+    }
+
+    @Override
+    public XirSnippet genMonitorEnter(XirSite site, XirArgument receiver, XirArgument lockAddress) {
+        return new XirSnippet(monitorEnterTemplates.get(site), receiver, lockAddress);
+    }
+
+    @Override
+    public XirSnippet genMonitorExit(XirSite site, XirArgument receiver, XirArgument lockAddress) {
+        return new XirSnippet(monitorExitTemplates.get(site), receiver, lockAddress);
+    }
+
+    @Override
+    public XirSnippet genNewInstance(XirSite site, JavaType type) {
+        HotSpotResolvedJavaType resolvedType = (HotSpotResolvedJavaType) type;
+        int instanceSize = resolvedType.instanceSize();
+        assert instanceSize >= 0;
+        return new XirSnippet(newInstanceTemplates.get(site, instanceSize), XirArgument.forObject(resolvedType.klassOop()));
+    }
+
+    @Override
+    public XirSnippet genNewArray(XirSite site, XirArgument length, Kind elementKind, JavaType componentType, JavaType arrayType) {
+        if (elementKind == Kind.Object) {
+            assert arrayType instanceof ResolvedJavaType;
+            return new XirSnippet(newObjectArrayTemplates.get(site), length, XirArgument.forObject(((HotSpotJavaType) arrayType).klassOop()));
+        } else {
+            assert arrayType == null;
+            JavaType primitiveArrayType = compiler.getCompilerToVM().getPrimitiveArrayType(elementKind);
+            return new XirSnippet(newTypeArrayTemplates.get(site, elementKind), length, XirArgument.forObject(((HotSpotJavaType) primitiveArrayType).klassOop()));
+        }
+    }
+
+    @Override
+    public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, JavaType type) {
+        XirArgument[] params = Arrays.copyOf(lengths, lengths.length + 1);
+        params[lengths.length] = XirArgument.forObject(((HotSpotJavaType) type).klassOop());
+        return new XirSnippet(multiNewArrayTemplate.get(site, lengths.length), params);
+    }
+
+    @Override
+    public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile) {
+        final boolean useCounters = GraalOptions.SnippetCounters;
+        TypeCheckHints hints = new TypeCheckHints(type, profile, site.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints);
+        int hintsLength = hints.types.length;
+        if (hintsLength == 0) {
+            if (useCounters) {
+                if (type == null) {
+                    return new XirSnippet(checkCastTemplates.get(site, 0, NULL_TYPE), XirArgument.forObject(checkcastCounters), receiver, hub);
+                } else if (type.isInterface()) {
+                    return new XirSnippet(checkCastTemplates.get(site, 0, INTERFACE_TYPE), XirArgument.forObject(checkcastCounters), receiver, hub);
+                } else {
+                    return new XirSnippet(checkCastTemplates.get(site, 0), XirArgument.forObject(checkcastCounters), receiver, hub);
+                }
+            } else {
+                return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub);
+            }
+        } else {
+            XirArgument[] params = new XirArgument[(useCounters ? 1 : 0) + hintsLength + (hints.exact ? 1 : 2)];
+            int i = 0;
+            if (useCounters) {
+                params[i++] = XirArgument.forObject(checkcastCounters);
+            }
+            params[i++] = receiver;
+            if (!hints.exact) {
+                params[i++] = hub;
+            }
+            for (ResolvedJavaType hint : hints.types) {
+                params[i++] = XirArgument.forObject(((HotSpotJavaType) hint).klassOop());
+            }
+            XirTemplate template = hints.exact ? checkCastTemplates.get(site, hintsLength, EXACT_HINTS) : checkCastTemplates.get(site, hintsLength);
+            return new XirSnippet(template, params);
+        }
+    }
+
+    @Override
+    public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile) {
+        TypeCheckHints hints = new TypeCheckHints(type, profile, site.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints);
+        int hintsLength = hints.types.length;
+        if (hintsLength == 0) {
+            return new XirSnippet(instanceOfTemplates.get(site, 0), object, hub);
+        } else {
+            XirArgument[] params = new XirArgument[hintsLength + (hints.exact ? 1 : 2)];
+            int i = 0;
+            params[i++] = object;
+            if (!hints.exact) {
+                params[i++] = hub;
+            }
+            for (ResolvedJavaType hint : hints.types) {
+                params[i++] = XirArgument.forObject(((HotSpotJavaType) hint).klassOop());
+            }
+            XirTemplate template = hints.exact ? instanceOfTemplates.get(site, hintsLength, EXACT_HINTS) : instanceOfTemplates.get(site, hintsLength);
+            return new XirSnippet(template, params);
+        }
+    }
+
+    @Override
+    public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, ResolvedJavaType type, JavaTypeProfile profile) {
+        TypeCheckHints hints = new TypeCheckHints(type, profile, site.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints);
+        int hintsLength = hints.types.length;
+        if (hintsLength == 0) {
+            return new XirSnippet(materializeInstanceOfTemplates.get(site, 0), object, hub, trueValue, falseValue);
+        } else {
+            XirArgument[] params = new XirArgument[hintsLength + (hints.exact ? 3 : 4)];
+            int i = 0;
+            params[i++] = object;
+            if (!hints.exact) {
+                params[i++] = hub;
+            }
+            params[i++] = trueValue;
+            params[i++] = falseValue;
+            for (ResolvedJavaType hint : hints.types) {
+                params[i++] = XirArgument.forObject(((HotSpotJavaType) hint).klassOop());
+            }
+            XirTemplate template = hints.exact ? materializeInstanceOfTemplates.get(site, hintsLength, EXACT_HINTS) : materializeInstanceOfTemplates.get(site, hintsLength);
+            return new XirSnippet(template, params);
+        }
+    }
+
+    @Override
+    public XirSnippet genTypeBranch(XirSite site, XirArgument thisHub, XirArgument otherHub, JavaType type) {
+        assert type instanceof ResolvedJavaType;
+        return new XirSnippet(typeCheckTemplates.get(site), thisHub, otherHub);
+    }
+
+    @Override
+    public void initialize(XirAssembler asm) {
+        this.globalAsm = asm;
+    }
+
+    private void checkSubtype(XirAssembler asm, XirOperand result, XirOperand objHub, XirOperand hub) {
+        asm.push(objHub);
+        asm.push(hub);
+        asm.callRuntime(config.instanceofStub, null);
+        asm.pop(result);
+        asm.pop(result);
+    }
+
+    private static void useRegisters(XirAssembler asm, Register... registers) {
+        if (registers != null) {
+            for (Register register : registers) {
+                asm.createRegisterTemp("reg", Kind.Illegal, register);
+            }
+        }
+    }
+
+    public boolean is(TemplateFlag check, long flags) {
+        return (flags & check.bits()) == check.bits();
+    }
+
+    /**
+     * Base class for all the ondemand template generators. It is not normally subclassed directly, but through one of
+     * its subclasses (SimpleTemplates, KindTemplates, IndexTemplates).
+     */
+    private abstract class Templates {
+
+        private ConcurrentHashMap<Long, XirTemplate> templates = new ConcurrentHashMap<>();
+        private final long mask;
+
+        /**
+         * Each flag passed to this method will cause templates with and without it to be generated.
+         */
+        public Templates(TemplateFlag... flags) {
+            this.mask = getBits((int) INDEX_MASK, null, flags);
+        }
+
+        protected abstract XirTemplate create(XirAssembler asm, long flags);
+
+        protected long getBits(int index, XirSite site, TemplateFlag... flags) {
+            long bits = index;
+            if (site != null) {
+                bits |= site.requiresNullCheck() ? NULL_CHECK.bits() : 0;
+                bits |= site.requiresReadBarrier() ? READ_BARRIER.bits() : 0;
+                bits |= site.requiresWriteBarrier() ? WRITE_BARRIER.bits() : 0;
+                bits |= site.requiresArrayStoreCheck() ? STORE_CHECK.bits() : 0;
+                bits |= site.requiresBoundsCheck() ? BOUNDS_CHECK.bits() : 0;
+            }
+            if (flags != null) {
+                for (TemplateFlag flag : flags) {
+                    bits |= flag.bits();
+                }
+            }
+            return bits;
+        }
+
+        protected XirTemplate getInternal(long flags) {
+            long maskedFlags = flags & mask;
+            XirTemplate template = templates.get(maskedFlags);
+            if (template == null) {
+                template = create(HotSpotXirGenerator.this.globalAsm.copy(), maskedFlags);
+                templates.put(maskedFlags, template);
+            }
+            return template;
+        }
+    }
+
+    private abstract class SimpleTemplates extends Templates {
+
+        public SimpleTemplates(TemplateFlag... flags) {
+            super(flags);
+        }
+
+        public XirTemplate get(XirSite site, TemplateFlag... flags) {
+            return getInternal(getBits(0, site, flags));
+        }
+    }
+
+    private abstract class IndexTemplates extends Templates {
+
+        public IndexTemplates(TemplateFlag... flags) {
+            super(flags);
+        }
+
+        @Override
+        protected final XirTemplate create(XirAssembler asm, long flags) {
+            return create(asm, flags & FLAGS_MASK, (int) (flags & INDEX_MASK));
+        }
+
+        protected abstract XirTemplate create(XirAssembler asm, long flags, int index);
+
+        public XirTemplate get(XirSite site, int size, TemplateFlag... flags) {
+            return getInternal(getBits(size, site, flags));
+        }
+    }
+
+    private abstract class KindTemplates extends Templates {
+
+        public KindTemplates(TemplateFlag... flags) {
+            super(flags);
+        }
+
+        @Override
+        protected final XirTemplate create(XirAssembler asm, long flags) {
+            return create(asm, flags & FLAGS_MASK, Kind.VALUES[(int) (flags & INDEX_MASK)]);
+        }
+
+        protected abstract XirTemplate create(XirAssembler asm, long flags, Kind kind);
+
+        public XirTemplate get(XirSite site, Kind kind, TemplateFlag... flags) {
+            return getInternal(getBits(kind.ordinal(), site, flags));
+        }
+    }
+
+    private static void printCounter(PrintStream out, CheckcastCounter name, long count, long total) {
+        double percent = total == 0D ? 0D : ((double) (count * 100)) / total;
+        out.println(String.format("%16s: %5.2f%%%10d  // %s", name, percent, count, name.desc));
+    }
+
+    public static  void printCheckcastCounters(PrintStream out) {
+        class Count implements Comparable<Count> {
+            long c;
+            CheckcastCounter name;
+            Count(long c, CheckcastCounter name) {
+                this.c = c;
+                this.name = name;
+            }
+            public int compareTo(Count o) {
+                return (int) (o.c - c);
+            }
+        }
+
+        long total = 0;
+        Count[] counters = new Count[checkcastCounters.length];
+        for (int i = 0; i < counters.length; i++) {
+            counters[i] = new Count(checkcastCounters[i], CheckcastCounter.VALUES[i]);
+            total += checkcastCounters[i];
+        }
+        Arrays.sort(counters);
+
+        out.println();
+        out.println("** XIR checkcast counters **");
+        for (Count c : counters) {
+            printCounter(out, c.name, c.c, total);
+        }
+    }
+
+    public static void printCounters(PrintStream out) {
+        if (GraalOptions.SnippetCounters) {
+            printCheckcastCounters(out);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/TemplateFlag.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,48 @@
+/*
+ * 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.hotspot.target.amd64;
+
+enum TemplateFlag {
+    NULL_CHECK,
+    READ_BARRIER,
+    WRITE_BARRIER,
+    STORE_CHECK,
+    BOUNDS_CHECK,
+    GIVEN_LENGTH,
+    INPUTS_DIFFERENT,
+    INPUTS_SAME,
+    STATIC_METHOD,
+    SYNCHRONIZED,
+    INTERFACE_TYPE,
+    NULL_TYPE,
+    EXACT_HINTS;
+
+    private static final long FIRST_FLAG = 0x0000000100000000L;
+    public static final long FLAGS_MASK = 0x0000FFFF00000000L;
+    public static final long INDEX_MASK = 0x00000000FFFFFFFFL;
+
+    public long bits() {
+        assert ((FIRST_FLAG << ordinal()) & FLAGS_MASK) != 0;
+        return FIRST_FLAG << ordinal();
+    }
+}
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java	Wed Jul 18 10:50:57 2012 -0700
@@ -31,17 +31,8 @@
 import com.oracle.graal.bytecode.*;
 
 /**
- *
- * <h1>Implementation notes</h1>
- * <li>Native methods are invoked using standard java reflection.</li>
- *
- * <h1>Features:</h1>
- *
- *
- * <h1>Limitations:</h1>
- *
- * <li>The interpreter is not able to recognize a native method that calls a java method.
- *  In that case the java method will be interpreted directly on the vm interpreter.</li>
+ * High-level bytecode interpreter that executes on top of Java. Java native methods
+ * are executed using the {@link com.oracle.graal.api.interpreter.RuntimeInterpreterInterface}.
  */
 @SuppressWarnings("static-method")
 public final class BytecodeInterpreter implements Interpreter {
@@ -62,7 +53,6 @@
     private Map<ResolvedJavaMethod, MethodRedirectionInfo> methodDelegates;
 
     private int maxStackFrames;
-    private int stackFrameDepth;
 
     private ResolvedJavaMethod rootMethod;
     private RuntimeInterpreterInterface runtimeInterface;
@@ -95,36 +85,39 @@
     }
 
     private void registerDelegates() {
-       addDelegate(findMethod(Throwable.class, "fillInStackTrace"), new InterpreterCallable() {
-        @Override
-        public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable {
-            setBackTrace(caller, (Throwable) arguments[0], createStackTraceElements(caller));
-            return null;
-        }
-       });
-       addDelegate(findMethod(Throwable.class, "getStackTraceDepth"), new InterpreterCallable() {
-           @Override
-           public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable {
-               StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]);
-               if (elements != null) {
-                   return elements.length;
-               }
-               return 0;
-           }
-       });
-       addDelegate(findMethod(Throwable.class, "getStackTraceElement", int.class), new InterpreterCallable() {
-           @Override
-           public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable {
-               StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]);
-               if (elements != null) {
-                   Integer index = (Integer) arguments[0];
-                   if (index != null) {
-                       return elements[index];
-                   }
-               }
-               return null;
-           }
-       });
+        addDelegate(findMethod(Throwable.class, "fillInStackTrace"), new InterpreterCallable() {
+
+            @Override
+            public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable {
+                setBackTrace(caller, (Throwable) arguments[0], createStackTraceElements(caller));
+                return null;
+            }
+        });
+        addDelegate(findMethod(Throwable.class, "getStackTraceDepth"), new InterpreterCallable() {
+
+            @Override
+            public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable {
+                StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]);
+                if (elements != null) {
+                    return elements.length;
+                }
+                return 0;
+            }
+        });
+        addDelegate(findMethod(Throwable.class, "getStackTraceElement", int.class), new InterpreterCallable() {
+
+            @Override
+            public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable {
+                StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]);
+                if (elements != null) {
+                    Integer index = (Integer) arguments[0];
+                    if (index != null) {
+                        return elements[index];
+                    }
+                }
+                return null;
+            }
+        });
     }
 
     @SuppressWarnings("unused")
@@ -162,6 +155,10 @@
             assert boxedArguments != null;
             assert signature.argumentCount(receiver) == boxedArguments.length;
 
+            if (TRACE) {
+                trace(0, "Executing root method " + method);
+            }
+
             InterpreterFrame rootFrame = new InterpreterFrame(rootMethod, signature.argumentSlots(true));
             rootFrame.pushObject(this);
             rootFrame.pushObject(method);
@@ -173,7 +170,7 @@
                 index++;
             }
 
-            for (int i = 0; i < boxedArguments.length; i++, index++) {
+            for (int i = 0; index < boxedArguments.length; i++, index++) {
                 pushAsObject(rootFrame, signature.argumentKindAt(i), boxedArguments[index]);
             }
 
@@ -181,6 +178,7 @@
             executeRoot(rootFrame, frame);
             return popAsObject(rootFrame, signature.returnKind());
         } catch (Exception e) {
+            // TODO (chaeubl): remove this exception handler (only used for debugging)
             throw e;
         }
     }
@@ -194,9 +192,7 @@
     }
 
     private void executeRoot(InterpreterFrame root, InterpreterFrame frame) throws Throwable {
-        //TODO reflection redirection
-        stackFrameDepth = 0;
-
+        // TODO reflection redirection
         InterpreterFrame prevFrame = frame;
         InterpreterFrame currentFrame = frame;
         BytecodeStream bs = new BytecodeStream(currentFrame.getMethod().code());
@@ -220,17 +216,17 @@
             while (true) {
                 int result = executeInstruction(frame, bs);
                 switch (result) {
-                    case NEXT :
+                    case NEXT:
                         bs.next();
                         break;
-                    case RETURN :
+                    case RETURN:
                         return popFrame(frame);
                     case CALL:
                         return allocateFrame(frame, bs);
-                    case BRANCH :
+                    case BRANCH:
                         bs.setBCI(bs.readBranchDest());
                         break;
-                    default :
+                    default:
                         // the outcome depends on stack values
                         assert result >= 0 : "negative branch target";
                         bs.setBCI(result);
@@ -239,7 +235,7 @@
             }
         } catch (Throwable t) {
             if (TRACE) {
-                traceOp("Exception " + t.toString());
+                traceOp(frame, "Exception " + t.toString());
             }
             updateStackTrace(frame, t);
 
@@ -252,7 +248,7 @@
                 throw t;
             } else {
                 if (TRACE) {
-                    traceOp("Handler found " + handlerFrame.getMethod() + ":" + handlerFrame.getBCI());
+                    traceOp(frame, "Handler found " + handlerFrame.getMethod() + ":" + handlerFrame.getBCI());
                 }
                 // update bci from frame
                 bs.setBCI(handlerFrame.getBCI());
@@ -268,79 +264,80 @@
 
     private int executeInstruction(InterpreterFrame frame, BytecodeStream bs) throws Throwable {
         if (TRACE_BYTE_CODE) {
-            traceOp(bs.currentBCI() + ": " + Bytecodes.baseNameOf(bs.currentBC()));
+            traceOp(frame, bs.currentBCI() + ": " + Bytecodes.baseNameOf(bs.currentBC()));
         }
-        switch(bs.currentBC()) {
-            case Bytecodes.NOP            : break;
-            case Bytecodes.ACONST_NULL    :
+        switch (bs.currentBC()) {
+            case Bytecodes.NOP:
+                break;
+            case Bytecodes.ACONST_NULL:
                 frame.pushObject(null);
                 break;
-            case Bytecodes.ICONST_M1      :
+            case Bytecodes.ICONST_M1:
                 frame.pushInt(-1);
                 break;
-            case Bytecodes.ICONST_0       :
+            case Bytecodes.ICONST_0:
                 frame.pushInt(0);
                 break;
-            case Bytecodes.ICONST_1       :
+            case Bytecodes.ICONST_1:
                 frame.pushInt(1);
                 break;
-            case Bytecodes.ICONST_2       :
+            case Bytecodes.ICONST_2:
                 frame.pushInt(2);
                 break;
-            case Bytecodes.ICONST_3       :
+            case Bytecodes.ICONST_3:
                 frame.pushInt(3);
                 break;
-            case Bytecodes.ICONST_4       :
+            case Bytecodes.ICONST_4:
                 frame.pushInt(4);
                 break;
-            case Bytecodes.ICONST_5       :
+            case Bytecodes.ICONST_5:
                 frame.pushInt(5);
                 break;
-            case Bytecodes.LCONST_0       :
+            case Bytecodes.LCONST_0:
                 frame.pushLong(0L);
                 break;
-            case Bytecodes.LCONST_1       :
+            case Bytecodes.LCONST_1:
                 frame.pushLong(1L);
                 break;
-            case Bytecodes.FCONST_0       :
+            case Bytecodes.FCONST_0:
                 frame.pushFloat(0.0F);
                 break;
-            case Bytecodes.FCONST_1       :
+            case Bytecodes.FCONST_1:
                 frame.pushFloat(1.0F);
                 break;
-            case Bytecodes.FCONST_2       :
+            case Bytecodes.FCONST_2:
                 frame.pushFloat(2.0F);
                 break;
-            case Bytecodes.DCONST_0       :
+            case Bytecodes.DCONST_0:
                 frame.pushDouble(0.0D);
                 break;
-            case Bytecodes.DCONST_1       :
+            case Bytecodes.DCONST_1:
                 frame.pushDouble(1.0D);
                 break;
-            case Bytecodes.BIPUSH         :
+            case Bytecodes.BIPUSH:
                 frame.pushInt(bs.readByte());
                 break;
-            case Bytecodes.SIPUSH         :
+            case Bytecodes.SIPUSH:
                 frame.pushInt(bs.readShort());
                 break;
-            case Bytecodes.LDC            :
-            case Bytecodes.LDC_W          :
-            case Bytecodes.LDC2_W         :
+            case Bytecodes.LDC:
+            case Bytecodes.LDC_W:
+            case Bytecodes.LDC2_W:
                 pushCPConstant(frame, bs.readCPI());
                 break;
-            case Bytecodes.ILOAD          :
+            case Bytecodes.ILOAD:
                 frame.pushInt(frame.getInt(frame.resolveLocalIndex(bs.readLocalIndex())));
                 break;
-            case Bytecodes.LLOAD          :
+            case Bytecodes.LLOAD:
                 frame.pushLong(frame.getLong(frame.resolveLocalIndex(bs.readLocalIndex())));
                 break;
-            case Bytecodes.FLOAD          :
+            case Bytecodes.FLOAD:
                 frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(bs.readLocalIndex())));
                 break;
-            case Bytecodes.DLOAD          :
+            case Bytecodes.DLOAD:
                 frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(bs.readLocalIndex())));
                 break;
-            case Bytecodes.ALOAD          :
+            case Bytecodes.ALOAD:
                 frame.pushObject(frame.getObject(frame.resolveLocalIndex(bs.readLocalIndex())));
                 break;
             case Bytecodes.ILOAD_0:
@@ -355,441 +352,441 @@
             case Bytecodes.ILOAD_3:
                 frame.pushInt(frame.getInt(frame.resolveLocalIndex(3)));
                 break;
-            case Bytecodes.LLOAD_0        :
+            case Bytecodes.LLOAD_0:
                 frame.pushLong(frame.getLong(frame.resolveLocalIndex(0)));
                 break;
-            case Bytecodes.LLOAD_1        :
+            case Bytecodes.LLOAD_1:
                 frame.pushLong(frame.getLong(frame.resolveLocalIndex(1)));
                 break;
-            case Bytecodes.LLOAD_2        :
+            case Bytecodes.LLOAD_2:
                 frame.pushLong(frame.getLong(frame.resolveLocalIndex(2)));
                 break;
-            case Bytecodes.LLOAD_3        :
+            case Bytecodes.LLOAD_3:
                 frame.pushLong(frame.getLong(frame.resolveLocalIndex(3)));
                 break;
-            case Bytecodes.FLOAD_0        :
+            case Bytecodes.FLOAD_0:
                 frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(0)));
                 break;
-            case Bytecodes.FLOAD_1        :
+            case Bytecodes.FLOAD_1:
                 frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(1)));
                 break;
-            case Bytecodes.FLOAD_2        :
+            case Bytecodes.FLOAD_2:
                 frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(2)));
                 break;
-            case Bytecodes.FLOAD_3        :
+            case Bytecodes.FLOAD_3:
                 frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(3)));
                 break;
-            case Bytecodes.DLOAD_0        :
+            case Bytecodes.DLOAD_0:
                 frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(0)));
                 break;
-            case Bytecodes.DLOAD_1        :
+            case Bytecodes.DLOAD_1:
                 frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(1)));
                 break;
-            case Bytecodes.DLOAD_2        :
+            case Bytecodes.DLOAD_2:
                 frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(2)));
                 break;
-            case Bytecodes.DLOAD_3        :
+            case Bytecodes.DLOAD_3:
                 frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(3)));
                 break;
-            case Bytecodes.ALOAD_0        :
+            case Bytecodes.ALOAD_0:
                 frame.pushObject(frame.getObject(frame.resolveLocalIndex(0)));
                 break;
-            case Bytecodes.ALOAD_1        :
+            case Bytecodes.ALOAD_1:
                 frame.pushObject(frame.getObject(frame.resolveLocalIndex(1)));
                 break;
-            case Bytecodes.ALOAD_2        :
+            case Bytecodes.ALOAD_2:
                 frame.pushObject(frame.getObject(frame.resolveLocalIndex(2)));
                 break;
-            case Bytecodes.ALOAD_3        :
+            case Bytecodes.ALOAD_3:
                 frame.pushObject(frame.getObject(frame.resolveLocalIndex(3)));
                 break;
-            case Bytecodes.IALOAD         :
+            case Bytecodes.IALOAD:
                 frame.pushInt(runtimeInterface.getArrayInt(frame.popInt(), frame.popObject()));
                 break;
-            case Bytecodes.LALOAD         :
+            case Bytecodes.LALOAD:
                 frame.pushLong(runtimeInterface.getArrayLong(frame.popInt(), frame.popObject()));
                 break;
-            case Bytecodes.FALOAD         :
+            case Bytecodes.FALOAD:
                 frame.pushFloat(runtimeInterface.getArrayFloat(frame.popInt(), frame.popObject()));
                 break;
-            case Bytecodes.DALOAD         :
+            case Bytecodes.DALOAD:
                 frame.pushDouble(runtimeInterface.getArrayDouble(frame.popInt(), frame.popObject()));
                 break;
-            case Bytecodes.AALOAD         :
+            case Bytecodes.AALOAD:
                 frame.pushObject(runtimeInterface.getArrayObject(frame.popInt(), frame.popObject()));
                 break;
-            case Bytecodes.BALOAD         :
+            case Bytecodes.BALOAD:
                 frame.pushInt(runtimeInterface.getArrayByte(frame.popInt(), frame.popObject()));
                 break;
-            case Bytecodes.CALOAD         :
+            case Bytecodes.CALOAD:
                 frame.pushInt(runtimeInterface.getArrayChar(frame.popInt(), frame.popObject()));
                 break;
-             case Bytecodes.SALOAD:
+            case Bytecodes.SALOAD:
                 frame.pushInt(runtimeInterface.getArrayShort(frame.popInt(), frame.popObject()));
                 break;
             case Bytecodes.ISTORE:
                 frame.setInt(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popInt());
                 break;
-            case Bytecodes.LSTORE         :
+            case Bytecodes.LSTORE:
                 frame.setLong(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popLong());
                 break;
-            case Bytecodes.FSTORE         :
+            case Bytecodes.FSTORE:
                 frame.setFloat(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popFloat());
                 break;
-            case Bytecodes.DSTORE         :
+            case Bytecodes.DSTORE:
                 frame.setDouble(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popDouble());
                 break;
-            case Bytecodes.ASTORE         :
+            case Bytecodes.ASTORE:
                 frame.setObject(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popObject());
                 break;
-            case Bytecodes.ISTORE_0       :
+            case Bytecodes.ISTORE_0:
                 frame.setInt(frame.resolveLocalIndex(0), frame.popInt());
                 break;
-            case Bytecodes.ISTORE_1       :
+            case Bytecodes.ISTORE_1:
                 frame.setInt(frame.resolveLocalIndex(1), frame.popInt());
                 break;
-            case Bytecodes.ISTORE_2       :
+            case Bytecodes.ISTORE_2:
                 frame.setInt(frame.resolveLocalIndex(2), frame.popInt());
                 break;
-            case Bytecodes.ISTORE_3       :
+            case Bytecodes.ISTORE_3:
                 frame.setInt(frame.resolveLocalIndex(3), frame.popInt());
                 break;
-            case Bytecodes.LSTORE_0       :
+            case Bytecodes.LSTORE_0:
                 frame.setLong(frame.resolveLocalIndex(0), frame.popLong());
                 break;
-            case Bytecodes.LSTORE_1       :
+            case Bytecodes.LSTORE_1:
                 frame.setLong(frame.resolveLocalIndex(1), frame.popLong());
                 break;
-            case Bytecodes.LSTORE_2       :
+            case Bytecodes.LSTORE_2:
                 frame.setLong(frame.resolveLocalIndex(2), frame.popLong());
                 break;
-            case Bytecodes.LSTORE_3       :
+            case Bytecodes.LSTORE_3:
                 frame.setLong(frame.resolveLocalIndex(3), frame.popLong());
                 break;
-            case Bytecodes.FSTORE_0       :
+            case Bytecodes.FSTORE_0:
                 frame.setFloat(frame.resolveLocalIndex(0), frame.popFloat());
                 break;
-            case Bytecodes.FSTORE_1       :
+            case Bytecodes.FSTORE_1:
                 frame.setFloat(frame.resolveLocalIndex(1), frame.popFloat());
                 break;
-            case Bytecodes.FSTORE_2       :
+            case Bytecodes.FSTORE_2:
                 frame.setFloat(frame.resolveLocalIndex(2), frame.popFloat());
                 break;
-            case Bytecodes.FSTORE_3       :
+            case Bytecodes.FSTORE_3:
                 frame.setFloat(frame.resolveLocalIndex(3), frame.popFloat());
                 break;
-            case Bytecodes.DSTORE_0       :
+            case Bytecodes.DSTORE_0:
                 frame.setDouble(frame.resolveLocalIndex(0), frame.popDouble());
                 break;
-            case Bytecodes.DSTORE_1       :
+            case Bytecodes.DSTORE_1:
                 frame.setDouble(frame.resolveLocalIndex(1), frame.popDouble());
                 break;
-            case Bytecodes.DSTORE_2       :
+            case Bytecodes.DSTORE_2:
                 frame.setDouble(frame.resolveLocalIndex(2), frame.popDouble());
                 break;
-            case Bytecodes.DSTORE_3       :
+            case Bytecodes.DSTORE_3:
                 frame.setDouble(frame.resolveLocalIndex(3), frame.popDouble());
                 break;
-            case Bytecodes.ASTORE_0       :
+            case Bytecodes.ASTORE_0:
                 frame.setObject(frame.resolveLocalIndex(0), frame.popObject());
                 break;
-            case Bytecodes.ASTORE_1       :
+            case Bytecodes.ASTORE_1:
                 frame.setObject(frame.resolveLocalIndex(1), frame.popObject());
                 break;
-            case Bytecodes.ASTORE_2       :
+            case Bytecodes.ASTORE_2:
                 frame.setObject(frame.resolveLocalIndex(2), frame.popObject());
                 break;
-            case Bytecodes.ASTORE_3       :
+            case Bytecodes.ASTORE_3:
                 frame.setObject(frame.resolveLocalIndex(3), frame.popObject());
                 break;
-            case Bytecodes.IASTORE        :
+            case Bytecodes.IASTORE:
                 runtimeInterface.setArrayInt(frame.popInt(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.LASTORE        :
+            case Bytecodes.LASTORE:
                 runtimeInterface.setArrayLong(frame.popLong(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.FASTORE        :
+            case Bytecodes.FASTORE:
                 runtimeInterface.setArrayFloat(frame.popFloat(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.DASTORE        :
+            case Bytecodes.DASTORE:
                 runtimeInterface.setArrayDouble(frame.popDouble(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.AASTORE        :
+            case Bytecodes.AASTORE:
                 runtimeInterface.setArrayObject(frame.popObject(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.BASTORE        :
+            case Bytecodes.BASTORE:
                 runtimeInterface.setArrayByte((byte) frame.popInt(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.CASTORE        :
+            case Bytecodes.CASTORE:
                 runtimeInterface.setArrayChar((char) frame.popInt(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.SASTORE        :
+            case Bytecodes.SASTORE:
                 runtimeInterface.setArrayShort((short) frame.popInt(), frame.popInt(), frame.popObject());
                 break;
-            case Bytecodes.POP            :
+            case Bytecodes.POP:
                 frame.popVoid(1);
                 break;
-            case Bytecodes.POP2           :
+            case Bytecodes.POP2:
                 frame.popVoid(2);
                 break;
-            case Bytecodes.DUP            :
+            case Bytecodes.DUP:
                 frame.dup(1);
                 break;
-            case Bytecodes.DUP_X1         :
+            case Bytecodes.DUP_X1:
                 frame.dupx1();
                 break;
-            case Bytecodes.DUP_X2         :
+            case Bytecodes.DUP_X2:
                 frame.dupx2();
                 break;
-            case Bytecodes.DUP2           :
+            case Bytecodes.DUP2:
                 frame.dup(2);
                 break;
-            case Bytecodes.DUP2_X1        :
+            case Bytecodes.DUP2_X1:
                 frame.dup2x1();
                 break;
-            case Bytecodes.DUP2_X2        :
+            case Bytecodes.DUP2_X2:
                 frame.dup2x2();
                 break;
-            case Bytecodes.SWAP           :
+            case Bytecodes.SWAP:
                 frame.swapSingle();
                 break;
-            case Bytecodes.IADD           :
+            case Bytecodes.IADD:
                 frame.pushInt(frame.popInt() + frame.popInt());
                 break;
-            case Bytecodes.LADD           :
+            case Bytecodes.LADD:
                 frame.pushLong(frame.popLong() + frame.popLong());
                 break;
-            case Bytecodes.FADD           :
+            case Bytecodes.FADD:
                 frame.pushFloat(frame.popFloat() + frame.popFloat());
                 break;
-            case Bytecodes.DADD           :
+            case Bytecodes.DADD:
                 frame.pushDouble(frame.popDouble() + frame.popDouble());
                 break;
-            case Bytecodes.ISUB           :
+            case Bytecodes.ISUB:
                 frame.pushInt(-frame.popInt() + frame.popInt());
                 break;
-            case Bytecodes.LSUB           :
+            case Bytecodes.LSUB:
                 frame.pushLong(-frame.popLong() + frame.popLong());
                 break;
-            case Bytecodes.FSUB           :
+            case Bytecodes.FSUB:
                 frame.pushFloat(-frame.popFloat() + frame.popFloat());
                 break;
-            case Bytecodes.DSUB           :
+            case Bytecodes.DSUB:
                 frame.pushDouble(-frame.popDouble() + frame.popDouble());
                 break;
-            case Bytecodes.IMUL           :
+            case Bytecodes.IMUL:
                 frame.pushInt(frame.popInt() * frame.popInt());
                 break;
-            case Bytecodes.LMUL           :
+            case Bytecodes.LMUL:
                 frame.pushLong(frame.popLong() * frame.popLong());
                 break;
-            case Bytecodes.FMUL           :
+            case Bytecodes.FMUL:
                 frame.pushFloat(frame.popFloat() * frame.popFloat());
                 break;
-            case Bytecodes.DMUL           :
+            case Bytecodes.DMUL:
                 frame.pushDouble(frame.popDouble() * frame.popDouble());
                 break;
-            case Bytecodes.IDIV           :
+            case Bytecodes.IDIV:
                 divInt(frame);
                 break;
-            case Bytecodes.LDIV           :
+            case Bytecodes.LDIV:
                 divLong(frame);
                 break;
-            case Bytecodes.FDIV           :
+            case Bytecodes.FDIV:
                 divFloat(frame);
                 break;
-            case Bytecodes.DDIV           :
+            case Bytecodes.DDIV:
                 divDouble(frame);
                 break;
-            case Bytecodes.IREM           :
+            case Bytecodes.IREM:
                 remInt(frame);
                 break;
-            case Bytecodes.LREM           :
+            case Bytecodes.LREM:
                 remLong(frame);
                 break;
-            case Bytecodes.FREM           :
+            case Bytecodes.FREM:
                 remFloat(frame);
                 break;
-            case Bytecodes.DREM           :
+            case Bytecodes.DREM:
                 remDouble(frame);
                 break;
-            case Bytecodes.INEG           :
+            case Bytecodes.INEG:
                 frame.pushInt(-frame.popInt());
                 break;
-            case Bytecodes.LNEG           :
+            case Bytecodes.LNEG:
                 frame.pushLong(-frame.popLong());
                 break;
-            case Bytecodes.FNEG           :
+            case Bytecodes.FNEG:
                 frame.pushFloat(-frame.popFloat());
                 break;
-            case Bytecodes.DNEG           :
+            case Bytecodes.DNEG:
                 frame.pushDouble(-frame.popDouble());
                 break;
-            case Bytecodes.ISHL           :
+            case Bytecodes.ISHL:
                 shiftLeftInt(frame);
                 break;
-            case Bytecodes.LSHL           :
+            case Bytecodes.LSHL:
                 shiftLeftLong(frame);
                 break;
-            case Bytecodes.ISHR           :
+            case Bytecodes.ISHR:
                 shiftRightSignedInt(frame);
                 break;
-            case Bytecodes.LSHR           :
+            case Bytecodes.LSHR:
                 shiftRightSignedLong(frame);
                 break;
-            case Bytecodes.IUSHR          :
+            case Bytecodes.IUSHR:
                 shiftRightUnsignedInt(frame);
                 break;
-            case Bytecodes.LUSHR          :
+            case Bytecodes.LUSHR:
                 shiftRightUnsignedLong(frame);
                 break;
-            case Bytecodes.IAND           :
+            case Bytecodes.IAND:
                 frame.pushInt(frame.popInt() & frame.popInt());
                 break;
-            case Bytecodes.LAND           :
+            case Bytecodes.LAND:
                 frame.pushLong(frame.popLong() & frame.popLong());
                 break;
-            case Bytecodes.IOR            :
+            case Bytecodes.IOR:
                 frame.pushInt(frame.popInt() | frame.popInt());
                 break;
-            case Bytecodes.LOR            :
+            case Bytecodes.LOR:
                 frame.pushLong(frame.popLong() | frame.popLong());
                 break;
-            case Bytecodes.IXOR           :
+            case Bytecodes.IXOR:
                 frame.pushInt(frame.popInt() ^ frame.popInt());
                 break;
-            case Bytecodes.LXOR           :
+            case Bytecodes.LXOR:
                 frame.pushLong(frame.popLong() ^ frame.popLong());
                 break;
-            case Bytecodes.IINC           :
+            case Bytecodes.IINC:
                 iinc(frame, bs);
                 break;
-            case Bytecodes.I2L            :
+            case Bytecodes.I2L:
                 frame.pushLong(frame.popInt());
                 break;
-            case Bytecodes.I2F            :
+            case Bytecodes.I2F:
                 frame.pushFloat(frame.popInt());
                 break;
-            case Bytecodes.I2D            :
+            case Bytecodes.I2D:
                 frame.pushDouble(frame.popInt());
                 break;
-            case Bytecodes.L2I            :
+            case Bytecodes.L2I:
                 frame.pushInt((int) frame.popLong());
                 break;
-            case Bytecodes.L2F            :
+            case Bytecodes.L2F:
                 frame.pushFloat(frame.popLong());
                 break;
-            case Bytecodes.L2D            :
+            case Bytecodes.L2D:
                 frame.pushDouble(frame.popLong());
                 break;
-            case Bytecodes.F2I            :
+            case Bytecodes.F2I:
                 frame.pushInt((int) frame.popFloat());
                 break;
-            case Bytecodes.F2L            :
+            case Bytecodes.F2L:
                 frame.pushLong((long) frame.popFloat());
                 break;
-            case Bytecodes.F2D            :
+            case Bytecodes.F2D:
                 frame.pushDouble(frame.popFloat());
                 break;
-            case Bytecodes.D2I            :
+            case Bytecodes.D2I:
                 frame.pushInt((int) frame.popDouble());
                 break;
-            case Bytecodes.D2L            :
+            case Bytecodes.D2L:
                 frame.pushLong((long) frame.popDouble());
                 break;
-            case Bytecodes.D2F            :
+            case Bytecodes.D2F:
                 frame.pushFloat((float) frame.popDouble());
                 break;
-            case Bytecodes.I2B            :
+            case Bytecodes.I2B:
                 frame.pushInt((byte) frame.popInt());
                 break;
-            case Bytecodes.I2C            :
+            case Bytecodes.I2C:
                 frame.pushInt((char) frame.popInt());
                 break;
-            case Bytecodes.I2S            :
+            case Bytecodes.I2S:
                 frame.pushInt((short) frame.popInt());
                 break;
-            case Bytecodes.LCMP           :
+            case Bytecodes.LCMP:
                 compareLong(frame);
                 break;
-            case Bytecodes.FCMPL          :
+            case Bytecodes.FCMPL:
                 compareFloatLess(frame);
                 break;
-            case Bytecodes.FCMPG          :
+            case Bytecodes.FCMPG:
                 compareFloatGreater(frame);
                 break;
-            case Bytecodes.DCMPL          :
+            case Bytecodes.DCMPL:
                 compareDoubleLess(frame);
                 break;
-            case Bytecodes.DCMPG          :
+            case Bytecodes.DCMPG:
                 compareDoubleGreater(frame);
                 break;
-            case Bytecodes.IFEQ           :
+            case Bytecodes.IFEQ:
                 if (frame.popInt() == 0) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IFNE           :
+            case Bytecodes.IFNE:
                 if (frame.popInt() != 0) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IFLT           :
+            case Bytecodes.IFLT:
                 if (frame.popInt() < 0) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IFGE           :
+            case Bytecodes.IFGE:
                 if (frame.popInt() >= 0) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IFGT           :
+            case Bytecodes.IFGT:
                 if (frame.popInt() > 0) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IFLE           :
+            case Bytecodes.IFLE:
                 if (frame.popInt() <= 0) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ICMPEQ      :
+            case Bytecodes.IF_ICMPEQ:
                 if (frame.popInt() == frame.popInt()) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ICMPNE      :
+            case Bytecodes.IF_ICMPNE:
                 if (frame.popInt() != frame.popInt()) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ICMPLT      :
+            case Bytecodes.IF_ICMPLT:
                 if (frame.popInt() > frame.popInt()) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ICMPGE      :
+            case Bytecodes.IF_ICMPGE:
                 if (frame.popInt() <= frame.popInt()) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ICMPGT      :
+            case Bytecodes.IF_ICMPGT:
                 if (frame.popInt() < frame.popInt()) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ICMPLE      :
+            case Bytecodes.IF_ICMPLE:
                 if (frame.popInt() >= frame.popInt()) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ACMPEQ      :
+            case Bytecodes.IF_ACMPEQ:
                 if (frame.popObject() == frame.popObject()) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IF_ACMPNE      :
+            case Bytecodes.IF_ACMPNE:
                 if (frame.popObject() != frame.popObject()) {
                     return BRANCH;
                 }
@@ -797,58 +794,58 @@
             case Bytecodes.GOTO:
             case Bytecodes.GOTO_W:
                 return BRANCH;
-            case Bytecodes.JSR            :
-            case Bytecodes.JSR_W          :
+            case Bytecodes.JSR:
+            case Bytecodes.JSR_W:
                 frame.pushInt(bs.currentBCI());
                 return BRANCH;
-            case Bytecodes.RET            :
+            case Bytecodes.RET:
                 return frame.getInt(frame.resolveLocalIndex(bs.readLocalIndex()));
-            case Bytecodes.TABLESWITCH    :
+            case Bytecodes.TABLESWITCH:
                 return tableSwitch(frame, bs);
-            case Bytecodes.LOOKUPSWITCH   :
+            case Bytecodes.LOOKUPSWITCH:
                 return lookupSwitch(frame, bs);
-            case Bytecodes.IRETURN        :
+            case Bytecodes.IRETURN:
                 frame.getParentFrame().pushInt(frame.popInt());
                 return RETURN;
-            case Bytecodes.LRETURN        :
+            case Bytecodes.LRETURN:
                 frame.getParentFrame().pushLong(frame.popLong());
                 return RETURN;
-            case Bytecodes.FRETURN        :
+            case Bytecodes.FRETURN:
                 frame.getParentFrame().pushFloat(frame.popFloat());
                 return RETURN;
-            case Bytecodes.DRETURN        :
+            case Bytecodes.DRETURN:
                 frame.getParentFrame().pushDouble(frame.popDouble());
                 return RETURN;
-            case Bytecodes.ARETURN        :
+            case Bytecodes.ARETURN:
                 frame.getParentFrame().pushObject(frame.popObject());
                 return RETURN;
-            case Bytecodes.RETURN         :
+            case Bytecodes.RETURN:
                 return RETURN;
-            case Bytecodes.GETSTATIC      :
+            case Bytecodes.GETSTATIC:
                 getField(frame, null, bs.currentBC(), bs.readCPI());
                 break;
-            case Bytecodes.PUTSTATIC      :
+            case Bytecodes.PUTSTATIC:
                 putStatic(frame, bs.readCPI());
                 break;
             case Bytecodes.GETFIELD:
                 getField(frame, nullCheck(frame.popObject()), bs.currentBC(), bs.readCPI());
                 break;
-            case Bytecodes.PUTFIELD       :
+            case Bytecodes.PUTFIELD:
                 putField(frame, bs.readCPI());
                 break;
-            case Bytecodes.INVOKEVIRTUAL  :
+            case Bytecodes.INVOKEVIRTUAL:
                 callFrame = invokeVirtual(frame, bs.readCPI());
                 if (callFrame == null) {
                     break;
                 }
                 return CALL;
-            case Bytecodes.INVOKESPECIAL  :
+            case Bytecodes.INVOKESPECIAL:
                 callFrame = invokeSpecial(frame, bs.readCPI());
                 if (callFrame == null) {
                     break;
                 }
                 return CALL;
-            case Bytecodes.INVOKESTATIC   :
+            case Bytecodes.INVOKESTATIC:
                 callFrame = invokeStatic(frame, bs.readCPI());
                 if (callFrame == null) {
                     break;
@@ -860,53 +857,57 @@
                     break;
                 }
                 return CALL;
-            case Bytecodes.XXXUNUSEDXXX   :
+            case Bytecodes.XXXUNUSEDXXX:
                 assert false : "unused bytecode used. behaviour unspecified.";
                 // nop
                 break;
-            case Bytecodes.NEW            :
+            case Bytecodes.NEW:
                 frame.pushObject(allocateInstance(frame, bs.readCPI()));
                 break;
-            case Bytecodes.NEWARRAY       :
+            case Bytecodes.NEWARRAY:
                 frame.pushObject(allocateNativeArray(frame, bs.readByte()));
                 break;
-            case Bytecodes.ANEWARRAY      :
+            case Bytecodes.ANEWARRAY:
                 frame.pushObject(allocateArray(frame, bs.readCPI()));
                 break;
-            case Bytecodes.ARRAYLENGTH    :
+            case Bytecodes.ARRAYLENGTH:
                 frame.pushInt(Array.getLength(nullCheck(frame.popObject())));
                 break;
-            case Bytecodes.ATHROW         :
-                throw (Throwable) frame.popObject();
-            case Bytecodes.CHECKCAST      :
+            case Bytecodes.ATHROW:
+                Throwable t = (Throwable) frame.popObject();
+                if ("break".equals(t.getMessage())) {
+                    t.printStackTrace();
+                }
+                throw t;
+            case Bytecodes.CHECKCAST:
                 checkCast(frame, bs.readCPI());
                 break;
-            case Bytecodes.INSTANCEOF     :
+            case Bytecodes.INSTANCEOF:
                 instanceOf(frame, bs.readCPI());
                 break;
-            case Bytecodes.MONITORENTER   :
+            case Bytecodes.MONITORENTER:
                 runtimeInterface.monitorEnter(frame.popObject());
                 break;
-            case Bytecodes.MONITOREXIT    :
+            case Bytecodes.MONITOREXIT:
                 runtimeInterface.monitorExit(frame.popObject());
                 break;
-            case Bytecodes.WIDE           :
+            case Bytecodes.WIDE:
                 assert false;
                 break;
-            case Bytecodes.MULTIANEWARRAY :
+            case Bytecodes.MULTIANEWARRAY:
                 frame.pushObject(allocateMultiArray(frame, bs.readCPI(), bs.readUByte(bs.currentBCI() + 3)));
                 break;
-            case Bytecodes.IFNULL         :
+            case Bytecodes.IFNULL:
                 if (frame.popObject() == null) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.IFNONNULL      :
+            case Bytecodes.IFNONNULL:
                 if (frame.popObject() != null) {
                     return BRANCH;
                 }
                 break;
-            case Bytecodes.BREAKPOINT     :
+            case Bytecodes.BREAKPOINT:
                 assert false : "no breakpoints supported at this time.";
                 break; // nop
         }
@@ -945,9 +946,8 @@
         }
     }
 
-
     private void setStackTrace(InterpreterFrame frame, Throwable t, StackTraceElement[] stackTrace) {
-      runtimeInterface.setFieldObject(stackTrace, t,  findThrowableField(frame, "stackTrace"));
+        runtimeInterface.setFieldObject(stackTrace, t, findThrowableField(frame, "stackTrace"));
     }
 
     private StackTraceElement[] getBackTrace(InterpreterFrame frame, Throwable t) {
@@ -973,10 +973,9 @@
                     catchType = resolveType(frame, Bytecodes.INSTANCEOF, (char) handler.catchTypeCPI());
                 }
 
-                if (catchType == null
-                                || catchType.toJava().isInstance(t)) {
+                if (catchType == null || catchType.toJava().isInstance(t)) {
                     // the first found exception handler is our exception handler
-                   return handler;
+                    return handler;
                 }
             }
         }
@@ -985,8 +984,6 @@
 
     private InterpreterFrame allocateFrame(InterpreterFrame frame, BytecodeStream bs) {
         try {
-            stackFrameDepth++;
-
             InterpreterFrame nextFrame = this.callFrame;
 
             assert nextFrame != null;
@@ -1000,7 +997,7 @@
             }
             if (Modifier.isSynchronized(nextFrame.getMethod().accessFlags())) {
                 if (TRACE) {
-                    traceOp("Method monitor enter");
+                    traceOp(frame, "Method monitor enter");
                 }
                 if (Modifier.isStatic(nextFrame.getMethod().accessFlags())) {
                     runtimeInterface.monitorEnter(nextFrame.getMethod().holder().toJava());
@@ -1022,7 +1019,7 @@
         InterpreterFrame parent = frame.getParentFrame();
         if (Modifier.isSynchronized(frame.getMethod().accessFlags())) {
             if (TRACE) {
-                traceOp("Method monitor exit");
+                traceOp(frame, "Method monitor exit");
             }
             if (Modifier.isStatic(frame.getMethod().accessFlags())) {
                 runtimeInterface.monitorExit(frame.getMethod().holder().toJava());
@@ -1036,19 +1033,17 @@
         if (TRACE) {
             traceCall(frame, "Ret");
         }
-        stackFrameDepth--;
 
         frame.dispose();
         return parent;
     }
 
-    private void traceOp(String opName) {
-        trace(stackFrameDepth + 1, opName);
+    private void traceOp(InterpreterFrame frame, String opName) {
+        trace(frame.depth(), opName);
     }
 
     private void traceCall(InterpreterFrame frame, String type) {
-        trace(stackFrameDepth, type + " " +
-                        frame.getMethod() + " - " + frame.getMethod().signature().asString());
+        trace(frame.depth(), type + " " + frame.getMethod() + " - " + frame.getMethod().signature().asString());
     }
 
     private void trace(int level, String message) {
@@ -1060,7 +1055,6 @@
         System.out.println(builder);
     }
 
-
     private void divInt(InterpreterFrame frame) {
         int dividend = frame.popInt();
         int divisor = frame.popInt();
@@ -1085,7 +1079,6 @@
         frame.pushDouble(divisor / dividend);
     }
 
-
     private void remInt(InterpreterFrame frame) {
         int dividend = frame.popInt();
         int divisor = frame.popInt();
@@ -1147,8 +1140,7 @@
     }
 
     private int lookupSwitch(InterpreterFrame frame, BytecodeStream bs) {
-        return lookupSearch(
-                        new BytecodeLookupSwitch(bs, bs.currentBCI()), frame.popInt());
+        return lookupSearch(new BytecodeLookupSwitch(bs, bs.currentBCI()), frame.popInt());
     }
 
     /**
@@ -1169,7 +1161,7 @@
                 return switchHelper.bci() + switchHelper.offsetAt(mid); // key found
             }
         }
-        return switchHelper.defaultTarget();  // key not found.
+        return switchHelper.defaultTarget(); // key not found.
     }
 
     private int tableSwitch(InterpreterFrame frame, BytecodeStream bs) {
@@ -1198,7 +1190,7 @@
         return constantPool.lookupType(cpi, opcode).resolve(frame.getMethod().holder());
     }
 
-    private ResolvedJavaType resolveType(InterpreterFrame frame, Class<?> javaClass) {
+    private ResolvedJavaType resolveType(InterpreterFrame frame, Class< ? > javaClass) {
         return metaAccessProvider.getResolvedJavaType(javaClass).resolve(frame.getMethod().holder());
     }
 
@@ -1215,9 +1207,7 @@
     }
 
     private void instanceOf(InterpreterFrame frame, char cpi) {
-        frame.pushInt(resolveType(frame, Bytecodes.INSTANCEOF, cpi).
-                        toJava().isInstance(frame.popObject())
-                        ? 1 : 0);
+        frame.pushInt(resolveType(frame, Bytecodes.INSTANCEOF, cpi).toJava().isInstance(frame.popObject()) ? 1 : 0);
     }
 
     private void pushCPConstant(InterpreterFrame frame, char cpi) {
@@ -1227,7 +1217,7 @@
         if (constant instanceof Constant) {
             Constant c = ((Constant) constant);
             switch (c.kind) {
-                case Int :
+                case Int:
                     frame.pushInt(c.asInt());
                     break;
                 case Float:
@@ -1236,10 +1226,10 @@
                 case Object:
                     frame.pushObject(c.asObject());
                     break;
-                case Double :
+                case Double:
                     frame.pushDouble(c.asDouble());
                     break;
-                case Long :
+                case Long:
                     frame.pushLong(c.asLong());
                     break;
                 default:
@@ -1288,6 +1278,7 @@
         }
         return value;
     }
+
     private InterpreterFrame invokeStatic(InterpreterFrame frame, char cpi) throws Throwable {
         return invoke(frame, resolveMethod(frame, Bytecodes.INVOKESTATIC, cpi), null);
     }
@@ -1340,7 +1331,7 @@
     }
 
     private InterpreterFrame invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object receiver) throws Throwable {
-        if (stackFrameDepth >= maxStackFrames) {
+        if (caller.depth() >= maxStackFrames) {
             throw new StackOverflowError("Maximum callstack of " + maxStackFrames + " exceeded.");
         }
 
@@ -1378,7 +1369,7 @@
 
         // current thread is low level and we also execute the target method in the low-level interpreter
         Object[] originalCalleeParameters = popArgumentsAsObject(caller, originalMethod, hasReceiver);
-        Object[] parameters = new Object[] {caller, originalMethod, originalCalleeParameters};
+        Object[] parameters = new Object[]{caller, originalMethod, originalCalleeParameters};
         Object returnValue = redirectionInfo.getTargetMethod().invoke(redirectionInfo.getReceiver(), parameters);
         pushAsObject(caller, originalMethod.signature().returnKind(), returnValue);
 
@@ -1415,21 +1406,21 @@
     private Object allocateNativeArray(InterpreterFrame frame, byte cpi) {
         // the constants for the cpi are loosely defined and no real cpi indices.
         switch (cpi) {
-            case 4 :
+            case 4:
                 return new byte[frame.popInt()];
-            case 8 :
+            case 8:
                 return new byte[frame.popInt()];
-            case 5 :
+            case 5:
                 return new char[frame.popInt()];
-            case 7 :
+            case 7:
                 return new double[frame.popInt()];
-            case 6 :
+            case 6:
                 return new float[frame.popInt()];
-            case 10 :
+            case 10:
                 return new int[frame.popInt()];
-            case 11 :
+            case 11:
                 return new long[frame.popInt()];
-            case 9 :
+            case 9:
                 return new short[frame.popInt()];
             default:
                 assert false : "unexpected case";
@@ -1456,52 +1447,52 @@
 
     private void putFieldStatic(InterpreterFrame frame, ResolvedJavaField field) {
         switch (field.kind()) {
-            case Boolean :
-            case Byte :
-            case Char :
-            case Short :
-            case Int :
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
                 runtimeInterface.setFieldInt(frame.popInt(), null, field);
                 break;
-            case Double :
+            case Double:
                 runtimeInterface.setFieldDouble(frame.popDouble(), null, field);
                 break;
-            case Float :
+            case Float:
                 runtimeInterface.setFieldFloat(frame.popFloat(), null, field);
                 break;
-            case Long :
+            case Long:
                 runtimeInterface.setFieldLong(frame.popLong(), null, field);
                 break;
-            case Object :
+            case Object:
                 runtimeInterface.setFieldObject(frame.popObject(), null, field);
                 break;
-            default :
+            default:
                 assert false : "unexpected case";
         }
     }
 
     private void putFieldVirtual(InterpreterFrame frame, ResolvedJavaField field) {
         switch (field.kind()) {
-            case Boolean :
-            case Byte :
-            case Char :
-            case Short :
-            case Int :
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
                 runtimeInterface.setFieldInt(frame.popInt(), nullCheck(frame.popObject()), field);
                 break;
-            case Double :
+            case Double:
                 runtimeInterface.setFieldDouble(frame.popDouble(), nullCheck(frame.popObject()), field);
                 break;
-            case Float :
+            case Float:
                 runtimeInterface.setFieldFloat(frame.popFloat(), nullCheck(frame.popObject()), field);
                 break;
-            case Long :
+            case Long:
                 runtimeInterface.setFieldLong(frame.popLong(), nullCheck(frame.popObject()), field);
                 break;
-            case Object :
+            case Object:
                 runtimeInterface.setFieldObject(frame.popObject(), nullCheck(frame.popObject()), field);
                 break;
-            default :
+            default:
                 assert false : "unexpected case";
         }
     }
@@ -1509,71 +1500,70 @@
     private void getField(InterpreterFrame frame, Object base, int opcode, char cpi) {
         ResolvedJavaField field = resolveField(frame, opcode, cpi);
         switch (field.kind()) {
-            case Boolean :
+            case Boolean:
                 frame.pushInt(runtimeInterface.getFieldBoolean(base, field) ? 1 : 0);
                 break;
-            case Byte :
+            case Byte:
                 frame.pushInt(runtimeInterface.getFieldByte(base, field));
                 break;
-            case Char :
+            case Char:
                 frame.pushInt(runtimeInterface.getFieldChar(base, field));
                 break;
-            case Short :
+            case Short:
                 frame.pushInt(runtimeInterface.getFieldShort(base, field));
                 break;
-            case Int :
+            case Int:
                 frame.pushInt(runtimeInterface.getFieldInt(base, field));
                 break;
-            case Double :
+            case Double:
                 frame.pushDouble(runtimeInterface.getFieldDouble(base, field));
                 break;
-            case Float :
+            case Float:
                 frame.pushFloat(runtimeInterface.getFieldFloat(base, field));
                 break;
-            case Long :
+            case Long:
                 frame.pushLong(runtimeInterface.getFieldLong(base, field));
                 break;
-            case Object :
+            case Object:
                 frame.pushObject(runtimeInterface.getFieldObject(base, field));
                 break;
-            default :
+            default:
                 assert false : "unexpected case";
         }
     }
 
-
     private int pushAsObject(InterpreterFrame frame, Kind typeKind, Object value) {
-        switch(typeKind) {
-            case Int :
+        switch (typeKind) {
+            case Int:
                 frame.pushInt((int) value);
                 break;
-            case Long :
+            case Long:
                 frame.pushLong((long) value);
                 return 2;
-            case Boolean :
+            case Boolean:
                 frame.pushInt(((boolean) value) ? 1 : 0);
                 break;
-            case Byte :
+            case Byte:
                 frame.pushInt((byte) value);
                 break;
-            case Char :
+            case Char:
                 frame.pushInt((char) value);
                 break;
-            case Double :
+            case Double:
                 frame.pushDouble((double) value);
                 return 2;
-            case Float :
+            case Float:
                 frame.pushFloat((float) value);
                 break;
-            case Short :
+            case Short:
                 frame.pushInt((short) value);
                 break;
-            case Object :
+            case Object:
                 frame.pushObject(value);
                 break;
-            case Void :
+            case Void:
                 return 0;
-            default :
+            default:
                 assert false : "case not specified";
         }
         return 1;
@@ -1581,27 +1571,27 @@
 
     private Object popAsObject(InterpreterFrame frame, Kind typeKind) {
         switch (typeKind) {
-            case Boolean :
+            case Boolean:
                 return frame.popInt() == 1 ? true : false;
-            case Byte :
+            case Byte:
                 return (byte) frame.popInt();
-            case Char :
+            case Char:
                 return (char) frame.popInt();
-            case Double :
+            case Double:
                 return frame.popDouble();
-            case Int :
+            case Int:
                 return frame.popInt();
-            case Float :
+            case Float:
                 return frame.popFloat();
-            case Long :
+            case Long:
                 return frame.popLong();
-            case Short :
+            case Short:
                 return (short) frame.popInt();
-            case Object :
+            case Object:
                 return frame.popObject();
-            case Void :
+            case Void:
                 return null;
-            default :
+            default:
                 assert false : "unexpected case";
         }
         return null;
@@ -1615,7 +1605,7 @@
         }
     }
 
-    private static Method findMethod(Class<?> clazz, String name, Class<?> ... parameters) {
+    private static Method findMethod(Class< ? > clazz, String name, Class< ? >... parameters) {
         try {
             return clazz.getDeclaredMethod(name, parameters);
         } catch (Exception e) {
@@ -1654,6 +1644,7 @@
     }
 
     private class MethodRedirectionInfo {
+
         private InterpreterCallable receiver;
         private Method method;
 
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterFrame.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterFrame.java	Wed Jul 18 10:50:57 2012 -0700
@@ -37,21 +37,23 @@
     private static final int SINGLE = 1;
 
     /** Pointer to the top-most stack frame element. */
+    private int depth;
     private int tos;
 
     public InterpreterFrame(ResolvedJavaMethod method, int additionalStackSpace) {
-        this(method, null, additionalStackSpace);
+        this(method, null, additionalStackSpace, 0);
     }
 
-    private InterpreterFrame(ResolvedJavaMethod method, InterpreterFrame parent, int additionalStackSpace) {
+    private InterpreterFrame(ResolvedJavaMethod method, InterpreterFrame parent, int additionalStackSpace, int depth) {
         super(method.maxLocals() + method.maxStackSize() + BASE_LENGTH + additionalStackSpace, parent);
         setMethod(method);
         setBCI(0);
+        this.depth = depth;
         this.tos = BASE_LENGTH;
     }
 
     public InterpreterFrame create(ResolvedJavaMethod method, boolean hasReceiver) {
-        InterpreterFrame frame = new InterpreterFrame(method, this, 0);
+        InterpreterFrame frame = new InterpreterFrame(method, this, 0, this.depth + 1);
         int length = method.signature().argumentSlots(hasReceiver);
 
         frame.pushVoid(method.maxLocals());
@@ -67,6 +69,10 @@
         return BASE_LENGTH + index;
     }
 
+    public int depth() {
+        return depth;
+    }
+
     private int stackTos() {
         return BASE_LENGTH + getMethod().maxLocals();
     }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Wed Jul 18 10:50:57 2012 -0700
@@ -527,7 +527,7 @@
                 // There is a path from a loop end to the method entry that does not pass the loop header.
                 // Therefore, the loop is non reducible (has more than one entry).
                 // We don't want to compile such methods because the IR only supports structured loops.
-                throw new BailoutException("Non-reducible loop");
+                throw new BailoutException("Non-reducible loop: %016x", loop);
             }
         } while (loopChanges);
     }
@@ -629,7 +629,7 @@
             }
 
             assert block.loops == 0;
-            block.loops = (long) 1 << (long) nextLoop;
+            block.loops = 1L << nextLoop;
             Debug.log("makeLoopHeader(%s) -> %x", block, block.loops);
             loopHeaders[nextLoop] = block;
             block.loopId = nextLoop;
@@ -660,7 +660,7 @@
         block.visited = true;
         block.active = true;
 
-        int loops = 0;
+        long loops = 0;
         for (Block successor : block.successors) {
             // Recursively process successors.
             loops |= computeBlockOrder(successor);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Jul 18 10:50:57 2012 -0700
@@ -696,7 +696,7 @@
     private void genNewPrimitiveArray(int typeCode) {
         Kind kind = arrayTypeCodeToKind(typeCode);
         ResolvedJavaType elementType = runtime.getResolvedJavaType(kind);
-        NewPrimitiveArrayNode nta = currentGraph.add(new NewPrimitiveArrayNode(frameState.ipop(), elementType));
+        NewPrimitiveArrayNode nta = currentGraph.add(new NewPrimitiveArrayNode(elementType, frameState.ipop()));
         frameState.apush(append(nta));
     }
 
@@ -1144,7 +1144,7 @@
                 int pos = 0;
                 ArrayList<Block> exitLoops = new ArrayList<>(Long.bitCount(exits));
                 do {
-                    int lMask = 1 << pos;
+                    long lMask = 1L << pos;
                     if ((exits & lMask) != 0) {
                         exitLoops.add(loopHeaders[pos]);
                         exits &= ~lMask;
@@ -1187,7 +1187,7 @@
     }
 
     private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) {
-        assert probability >= 0 && probability <= 1;
+        assert probability >= 0 && probability <= 1.01 : probability;
         if (probability == 0 && optimisticOpts.removeNeverExecutedCode()) {
             return currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode, graphId));
         } else {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/FloatingReads.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,83 @@
+/*
+ * 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.micro;
+
+import org.junit.*;
+
+
+public class FloatingReads {
+    public static long init = Runtime.getRuntime().totalMemory();
+    private final int f = 10;
+    private int a;
+    private int b;
+    private int c;
+
+    public int test(int d) {
+        a = 3;
+        b = 5;
+        c = 7;
+        for (int i = 0; i < d; i++) {
+            if (i % 2 == 0) {
+                a += b;
+            }
+            if (i % 4 == 0) {
+                b += c;
+            } else if (i % 3 == 0) {
+                b -= a;
+            }
+            if (i % 5 == 0) {
+                for (int j = 0; j < i; j++) {
+                    c += a;
+                }
+                a -= f;
+            }
+            b = a ^ c;
+            if (i % 6 == 0) {
+                c--;
+            } else if (i % 7 == 0) {
+                Runtime.getRuntime().totalMemory();
+            }
+        }
+        return a + b + c;
+    }
+
+    @Test
+    public void run0() {
+        Assert.assertEquals(-42, test(10));
+    }
+
+    @Test
+    public void run1() {
+        Assert.assertEquals(2147465134, test(1000));
+    }
+
+    @Test
+    public void run2() {
+        Assert.assertEquals(-3, test(1));
+    }
+
+    @Test
+    public void run3() {
+        Assert.assertEquals(15, test(0));
+    }
+}
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java	Wed Jul 18 10:50:57 2012 -0700
@@ -30,8 +30,10 @@
  */
 @SuppressWarnings("unused")
 public class Conditional01 {
-
     private static final int RAM_SIZE = 0x100;
+    private static final int init = new Random().nextInt();
+    private static final int init1 = new Register().val;
+    private static final Register init2 = new CPC().r1;
 
     public static int test(int arg) {
         Conditional01 c = new Conditional01();
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Wed Jul 18 10:50:57 2012 -0700
@@ -25,16 +25,13 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
-import java.util.*;
-
-import com.oracle.graal.api.code.CompilationResult.Mark;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.asm.TargetMethodAssembler.CallPositionListener;
 import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
 
 public class AMD64Call {
 
@@ -45,24 +42,40 @@
         @State protected LIRFrameState state;
 
         protected final Object targetMethod;
-        protected final Map<XirMark, Mark> marks;
+        protected final CallPositionListener callPositionListener;
 
-        public DirectCallOp(Object targetMethod, Value result, Value[] parameters, LIRFrameState state, Map<XirMark, Mark> marks) {
+        public DirectCallOp(Object targetMethod, Value result, Value[] parameters, LIRFrameState state, CallPositionListener callPositionListener) {
             this.targetMethod = targetMethod;
             this.result = result;
             this.parameters = parameters;
             this.state = state;
-            this.marks = marks;
+            this.callPositionListener = callPositionListener;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            callAlignment(tasm, masm);
-            if (marks != null) {
-                marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0]));
+            if (callPositionListener != null) {
+                callPositionListener.beforeCall(tasm);
+            }
+
+            emitAlignmentForDirectCall(tasm, masm);
+
+            if (callPositionListener != null) {
+                int pos = masm.codeBuffer.position();
+                callPositionListener.atCall(tasm);
+                assert pos == masm.codeBuffer.position() : "call position listener inserted code before an aligned call";
             }
             directCall(tasm, masm, targetMethod, state);
         }
+
+        protected void emitAlignmentForDirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            // make sure that the displacement word of the call ends up word aligned
+            int offset = masm.codeBuffer.position();
+            offset += tasm.target.arch.machineCodeCallDisplacementOffset;
+            while (offset++ % tasm.target.wordSize != 0) {
+                masm.nop();
+            }
+        }
     }
 
     @Opcode("CALL_INDIRECT")
@@ -72,38 +85,28 @@
         @Use({REG}) protected Value targetAddress;
         @State protected LIRFrameState state;
 
-        private final Object targetMethod;
-        private final Map<XirMark, Mark> marks;
+        protected final Object targetMethod;
+        protected final CallPositionListener callPositionListener;
 
-        public IndirectCallOp(Object targetMethod, Value result, Value[] parameters, Value targetAddress, LIRFrameState state, Map<XirMark, Mark> marks) {
+        public IndirectCallOp(Object targetMethod, Value result, Value[] parameters, Value targetAddress, LIRFrameState state, CallPositionListener callPositionListener) {
             this.targetMethod = targetMethod;
             this.result = result;
             this.parameters = parameters;
             this.targetAddress = targetAddress;
             this.state = state;
-            this.marks = marks;
+            this.callPositionListener = callPositionListener;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            callAlignment(tasm, masm);
-            if (marks != null) {
-                marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0]));
+            if (callPositionListener != null) {
+                callPositionListener.beforeCall(tasm);
+                callPositionListener.atCall(tasm);
             }
             indirectCall(tasm, masm, asRegister(targetAddress), targetMethod, state);
         }
     }
 
-
-    public static void callAlignment(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        // make sure that the displacement word of the call ends up word aligned
-        int offset = masm.codeBuffer.position();
-        offset += tasm.target.arch.machineCodeCallDisplacementOffset;
-        while (offset++ % tasm.target.wordSize != 0) {
-            masm.nop();
-        }
-    }
-
     public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRFrameState info) {
         int before = masm.codeBuffer.position();
         if (target instanceof RuntimeCall) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Wed Jul 18 10:50:57 2012 -0700
@@ -197,74 +197,4 @@
     public boolean hasArgInCallerFrame() {
         return hasArgInCallerFrame;
     }
-
-/*
-    private int lastDecodeStart;
-
-    private void printAssembly(TargetMethodAssembler tasm) {
-        byte[] currentBytes = tasm.asm.codeBuffer.copyData(lastDecodeStart, tasm.asm.codeBuffer.position());
-        if (currentBytes.length > 0) {
-            String disasm = tasm.runtime.disassemble(currentBytes, lastDecodeStart);
-            if (disasm.length() != 0) {
-                TTY.println(disasm);
-            } else {
-                TTY.println("Code [+%d]: %d bytes", lastDecodeStart, currentBytes.length);
-                Util.printBytes(lastDecodeStart, currentBytes, GraalOptions.PrintAssemblyBytesPerLine);
-            }
-        }
-        lastDecodeStart = tasm.asm.codeBuffer.position();
-    }
-
-
-    public static void printBlock(Block x) {
-        // print block id
-        TTY.print("B%d ", x.getId());
-
-        // print flags
-        if (x.isLoopHeader()) {
-            TTY.print("lh ");
-        }
-        if (x.isLoopEnd()) {
-            TTY.print("le ");
-        }
-
-        // print block bci range
-        TTY.print("[%d, %d] ", -1, -1);
-
-        // print predecessors and successors
-        if (x.numberOfPreds() > 0) {
-            TTY.print("preds: ");
-            for (int i = 0; i < x.numberOfPreds(); i++) {
-                TTY.print("B%d ", x.predAt(i).getId());
-            }
-        }
-
-        if (x.numberOfSux() > 0) {
-            TTY.print("sux: ");
-            for (int i = 0; i < x.numberOfSux(); i++) {
-                TTY.print("B%d ", x.suxAt(i).getId());
-            }
-        }
-
-        TTY.println();
-    }
-
-    public static void printLIR(List<Block> blocks) {
-        if (TTY.isSuppressed()) {
-            return;
-        }
-        TTY.println("LIR:");
-        int i;
-        for (i = 0; i < blocks.size(); i++) {
-            Block bb = blocks.get(i);
-            printBlock(bb);
-            TTY.println("__id_Instruction___________________________________________");
-            for (LIRInstruction op : bb.lir) {
-                TTY.println(op.toStringWithIdPrefix());
-                TTY.println();
-            }
-            TTY.println();
-        }
-    }
-*/
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Wed Jul 18 10:50:57 2012 -0700
@@ -276,7 +276,7 @@
                     long offset = calc.getOffset(field);
 
                     if (VALUE_CLASS.isAssignableFrom(type)) {
-                        assert Modifier.isProtected(field.getModifiers()) && !Modifier.isFinal(field.getModifiers()) : "Value field must not be declared final or private because it is modified by register allocator: " + field;
+                        assert Modifier.isProtected(field.getModifiers()) && !Modifier.isFinal(field.getModifiers()) : "Value field must not be declared final or [package] private because it is modified by register allocator: " + field;
                         OperandModeAnnotation annotation = getOperandModeAnnotation(field);
                         assert annotation != null : "Field must have operand mode annotation: " + field;
                         annotation.scalarOffsets.add(offset);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Wed Jul 18 10:50:57 2012 -0700
@@ -59,7 +59,11 @@
     }
 
     public static boolean verify(final LIRInstruction op) {
-        ValueProcedure allowedProc = new ValueProcedure() { @Override public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) { return allowed(op, value, mode, flags); } };
+        ValueProcedure allowedProc = new ValueProcedure() {
+            @Override public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+                return allowed(op, value, mode, flags);
+            }
+        };
 
         op.forEachInput(allowedProc);
         op.forEachAlive(allowedProc);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Wed Jul 18 10:50:57 2012 -0700
@@ -36,6 +36,25 @@
 
 public class TargetMethodAssembler {
 
+    /**
+     * A client interested in knowing the position(s) associated with a call instruction.
+     */
+    public interface CallPositionListener {
+        /**
+         * Notifies this listener that the code buffer is at the position before any alignment
+         * instructions are emitted for a call. This listener can safely emit instructions into
+         * the code buffer as the alignment has not yet been computed.
+         */
+        void beforeCall(TargetMethodAssembler tasm);
+
+        /**
+         * Notifies this listener that the code buffer is at the position after alignment
+         * instruction have been emitted but before the call instruction has been emitted.
+         * This listener must not emit instructions at this position.
+         */
+        void atCall(TargetMethodAssembler tasm);
+    }
+
     private static class ExceptionInfo {
         public final int codeOffset;
         public final LabelRef exceptionEdge;
@@ -82,11 +101,13 @@
         targetMethod.setFrameSize(frameSize);
     }
 
+    private static final CompilationResult.Mark[] NO_REFS = {};
+
     public CompilationResult.Mark recordMark(Object id) {
-        return targetMethod.recordMark(asm.codeBuffer.position(), id, null);
+        return targetMethod.recordMark(asm.codeBuffer.position(), id, NO_REFS);
     }
 
-    public CompilationResult.Mark recordMark(Object id, CompilationResult.Mark[] references) {
+    public CompilationResult.Mark recordMark(Object id, CompilationResult.Mark... references) {
         return targetMethod.recordMark(asm.codeBuffer.position(), id, references);
     }
 
@@ -111,51 +132,7 @@
         Debug.metric("SafepointsEmitted").add(targetMethod.getSafepoints().size());
         Debug.metric("DataPatches").add(targetMethod.getDataReferences().size());
         Debug.metric("ExceptionHandlersEmitted").add(targetMethod.getExceptionHandlers().size());
-
         Debug.log("Finished target method %s, isStub %b", name, isStub);
-/*
-        if (GraalOptions.PrintAssembly && !TTY.isSuppressed() && !isStub) {
-            Util.printSection("Target Method", Util.SECTION_CHARACTER);
-            TTY.println("Name: " + name);
-            TTY.println("Frame size: " + targetMethod.frameSize());
-            TTY.println("Register size: " + asm.target.arch.registerReferenceMapBitCount);
-
-            if (GraalOptions.PrintCodeBytes) {
-                Util.printSection("Code", Util.SUB_SECTION_CHARACTER);
-                TTY.println("Code: %d bytes", targetMethod.targetCodeSize());
-                Util.printBytes(0L, targetMethod.targetCode(), 0, targetMethod.targetCodeSize(), GraalOptions.PrintAssemblyBytesPerLine);
-            }
-
-            Util.printSection("Disassembly", Util.SUB_SECTION_CHARACTER);
-            String disassembly = runtime.disassemble(targetMethod);
-            TTY.println(disassembly);
-            boolean noDis = disassembly == null || disassembly.length() == 0;
-
-            Util.printSection("Safepoints", Util.SUB_SECTION_CHARACTER);
-            for (CiTargetMethod.Safepoint x : targetMethod.safepoints) {
-                TTY.println(x.toString());
-                if (noDis && x.debugInfo != null) {
-                    TTY.println(CiUtil.indent(x.debugInfo.toString(), "  "));
-                }
-            }
-
-            Util.printSection("Data Patches", Util.SUB_SECTION_CHARACTER);
-            for (CiTargetMethod.DataPatch x : targetMethod.dataReferences) {
-                TTY.println(x.toString());
-            }
-
-            Util.printSection("Marks", Util.SUB_SECTION_CHARACTER);
-            for (CiTargetMethod.Mark x : targetMethod.marks) {
-                TTY.println(x.toString());
-            }
-
-            Util.printSection("Exception Handlers", Util.SUB_SECTION_CHARACTER);
-            for (CiTargetMethod.ExceptionHandler x : targetMethod.exceptionHandlers) {
-                TTY.println(x.toString());
-            }
-        }
-*/
-
         return targetMethod;
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/Block.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/Block.java	Wed Jul 18 10:50:57 2012 -0700
@@ -53,7 +53,6 @@
     }
 
     public int getId() {
-        assert id >= 0;
         return id;
     }
 
@@ -157,6 +156,18 @@
             public Iterator<FixedNode> iterator() {
                 return new NodeIterator();
             }
+
+            @Override
+            public String toString() {
+                StringBuilder str = new StringBuilder().append('[');
+                for (FixedNode node : this) {
+                    str.append(node).append(", ");
+                }
+                if (str.length() > 1) {
+                    str.setLength(str.length() - 2);
+                }
+                return str.append(']').toString();
+            }
         };
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/CFGVerifier.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/CFGVerifier.java	Wed Jul 18 10:50:57 2012 -0700
@@ -25,6 +25,7 @@
 public class CFGVerifier {
     public static boolean verify(ControlFlowGraph cfg) {
         for (Block block : cfg.getBlocks()) {
+            assert block.getId() >= 0;
             assert cfg.getBlocks()[block.getId()] == block;
 
             for (Block pred : block.getPredecessors()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -62,13 +62,6 @@
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> debugProperties = super.getDebugProperties();
-        debugProperties.put("shortName", "B");
-        return debugProperties;
-    }
-
-    @Override
     public void simplify(SimplifierTool tool) {
         FixedNode prev = (FixedNode) this.predecessor();
         if (prev == null) {
@@ -78,6 +71,7 @@
         } else {
             // This begin node can be removed and all guards moved up to the preceding begin node.
             prepareDelete();
+            tool.addToWorkList(next());
             ((StructuredGraph) graph()).removeFixed(this);
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -31,6 +31,20 @@
 
     @Input protected final NodeInputList<ValueNode> arguments;
 
+    /**
+     * The address computation for an indirect call (e.g., invokevirtual or invokeinterface).
+     */
+    @Input protected ValueNode computedAddress;
+
+    public ValueNode computedAddress() {
+        return computedAddress;
+    }
+
+    public void setComputedAddress(ValueNode address) {
+        updateUsages(this.computedAddress, address);
+        this.computedAddress = address;
+    }
+
     public CallTargetNode(ValueNode[] arguments) {
         super(StampFactory.extension());
         this.arguments = new NodeInputList<>(this, arguments);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
@@ -32,7 +34,7 @@
  * The {@code ConstantNode} represents a constant such as an integer value,
  * long, float, object reference, address, etc.
  */
-@NodeInfo(shortName = "Const")
+@NodeInfo(shortName = "Const", nameTemplate = "Const({p#rawvalue})")
 public class ConstantNode extends BooleanNode implements LIRLowerable {
 
     public final Constant value;
@@ -219,6 +221,13 @@
     }
 
     @Override
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+        Map<Object, Object> properties = super.getDebugProperties(map);
+        properties.put("rawvalue", value.kind.isObject() ? value.kind.format(value.boxedValue()) : value.boxedValue());
+        return properties;
+    }
+
+    @Override
     public String toString(Verbosity verbosity) {
         if (verbosity == Verbosity.Name) {
             return super.toString(Verbosity.Name) + "(" + value.kind.format(value.boxedValue()) + ")";
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -85,17 +85,6 @@
         };
     }
 
-    @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> properties = super.getDebugProperties();
-        StringBuilder str = new StringBuilder();
-        for (int i = 0; i < branchProbability.length; i++) {
-            str.append(i == 0 ? "" : ", ").append(String.format(Locale.ENGLISH, "%7.5f", branchProbability[i]));
-        }
-        properties.put("branchProbability", str.toString());
-        return properties;
-    }
-
     public int blockSuccessorIndex(BeginNode successor) {
         int idx = blockSuccessors.indexOf(successor);
         if (idx < 0) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -28,7 +28,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-@NodeInfo(shortName = "Deopt")
+@NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}")
 public class DeoptimizeNode extends FixedNode implements Node.IterableNodeType, LIRLowerable {
 
     private String message;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -50,13 +50,6 @@
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> debugProperties = super.getDebugProperties();
-        debugProperties.put("shortName", "E");
-        return debugProperties;
-    }
-
-    @Override
     public Iterable< ? extends Node> cfgSuccessors() {
         return Arrays.asList(merge());
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -29,10 +29,11 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
+@NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}")
 public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, LIRLowerable, Node.IterableNodeType, Negatable {
 
     @Input private BooleanNode condition;
-    private final DeoptimizationReason deoptReason;
+    private final DeoptimizationReason reason;
     private final DeoptimizationAction action;
     private boolean negated;
     private final long leafGraphId;
@@ -56,7 +57,7 @@
         this.negated = negated;
         this.leafGraphId = leafGraphId;
         this.condition = condition;
-        this.deoptReason = deoptReason;
+        this.reason = deoptReason;
     }
 
     @Override
@@ -70,7 +71,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitGuardCheck(condition, deoptReason, action, negated, leafGraphId);
+        gen.emitGuardCheck(condition, reason, action, negated, leafGraphId);
     }
 
     @Override
@@ -84,7 +85,7 @@
                 if (next != null) {
                     tool.deleteBranch(next);
                 }
-                setNext(graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, deoptReason, leafGraphId)));
+                setNext(graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, reason, leafGraphId)));
                 return;
             }
         }
@@ -92,7 +93,7 @@
 
     @Override
     public void lower(LoweringTool tool) {
-        ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(tool.createGuard(condition, deoptReason, action, negated, leafGraphId)));
+        ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(tool.createGuard(condition, reason, action, negated, leafGraphId)));
         ((StructuredGraph) graph()).replaceFixedWithFixed(this, newAnchor);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Wed Jul 18 10:50:57 2012 -0700
@@ -35,6 +35,7 @@
  * The {@code FrameState} class encapsulates the frame state (i.e. local variables and
  * operand stack) at a particular point in the abstract interpretation.
  */
+@NodeInfo(nameTemplate = "FrameState@{p#method/s}:{p#bci}")
 public final class FrameState extends VirtualState implements Node.IterableNodeType, LIRLowerable {
 
     /**
@@ -352,30 +353,16 @@
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> properties = super.getDebugProperties();
-        properties.put("bci", bci);
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+        Map<Object, Object> properties = super.getDebugProperties(map);
         if (method != null) {
-            properties.put("method", MetaUtil.format("%H.%n(%p):%r", method));
+            //properties.put("method", MetaUtil.format("%H.%n(%p):%r", method));
             StackTraceElement ste = method.toStackTraceElement(bci);
             if (ste.getFileName() != null && ste.getLineNumber() >= 0) {
-                properties.put("source", ste.getFileName() + ":" + ste.getLineNumber());
+                properties.put("sourceFile", ste.getFileName());
+                properties.put("sourceLine", ste.getLineNumber());
             }
-        } else {
-            properties.put("method", "None");
-        }
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < localsSize(); i++) {
-            sb.append(i == 0 ? "" : ", ").append(localAt(i) == null ? "_" : localAt(i).toString(Verbosity.Id));
         }
-        properties.put("locals", sb.toString());
-        sb = new StringBuilder();
-        for (int i = 0; i < stackSize(); i++) {
-            sb.append(i == 0 ? "" : ", ").append(stackAt(i) == null ? "_" : stackAt(i).toString(Verbosity.Id));
-        }
-        properties.put("stack", sb.toString());
-        properties.put("rethrowException", rethrowException);
-        properties.put("duringCall", duringCall);
         return properties;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -41,6 +41,7 @@
  * maximum flexibility for the guard node and guarantees that deoptimization occurs only if the control flow would have
  * reached the guarded node (without taking exceptions into account).
  */
+@NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}")
 public final class GuardNode extends FloatingNode implements Canonicalizable, LIRLowerable, TypeFeedbackProvider, Node.IterableNodeType, Negatable {
 
     @Input private BooleanNode condition;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Wed Jul 18 10:50:57 2012 -0700
@@ -24,8 +24,9 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
 
-public interface Invoke extends StateSplit {
+public interface Invoke extends StateSplit, Lowerable {
 
     FixedNode next();
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -34,6 +34,7 @@
 /**
  * The {@code InvokeNode} represents all kinds of method calls.
  */
+@NodeInfo(nameTemplate = "Invoke#{p#targetMethod/s}")
 public final class InvokeNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, Invoke, LIRLowerable, MemoryCheckpoint  {
 
     @Input private final MethodCallTargetNode callTarget;
@@ -86,15 +87,20 @@
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> debugProperties = super.getDebugProperties();
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+        Map<Object, Object> debugProperties = super.getDebugProperties(map);
         if (callTarget != null && callTarget.targetMethod() != null) {
-            debugProperties.put("targetMethod", MetaUtil.format("%h.%n(%p)", callTarget.targetMethod()));
+            debugProperties.put("targetMethod", callTarget.targetMethod());
         }
         return debugProperties;
     }
 
     @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
+    }
+
+    @Override
     public void generate(LIRGeneratorTool gen) {
         gen.emitInvoke(this);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -30,7 +30,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
-
+@NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}")
 public class InvokeWithExceptionNode extends ControlSplitNode implements Node.IterableNodeType, Invoke, MemoryCheckpoint, LIRLowerable {
     public static final int NORMAL_EDGE = 0;
     public static final int EXCEPTION_EDGE = 1;
@@ -127,6 +127,11 @@
     }
 
     @Override
+    public void lower(LoweringTool tool) {
+        tool.getRuntime().lower(this, tool);
+    }
+
+    @Override
     public void generate(LIRGeneratorTool gen) {
         gen.emitInvoke(this);
     }
@@ -152,11 +157,10 @@
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> debugProperties = super.getDebugProperties();
-        debugProperties.put("memoryCheckpoint", "true");
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+        Map<Object, Object> debugProperties = super.getDebugProperties(map);
         if (callTarget != null && callTarget.targetMethod() != null) {
-            debugProperties.put("targetMethod", MetaUtil.format("%h.%n(%p)", callTarget.targetMethod()));
+            debugProperties.put("targetMethod", callTarget.targetMethod());
         }
         return debugProperties;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LocalNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LocalNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -30,7 +30,7 @@
  * The {@code Local} instruction is a placeholder for an incoming argument
  * to a function call.
  */
-
+@NodeInfo(nameTemplate = "Local({p#index})")
 public final class LocalNode extends FloatingNode implements Node.IterableNodeType {
 
     private final int index;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -140,13 +140,6 @@
         return super.verify();
     }
 
-    @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> properties = super.getDebugProperties();
-        properties.put("loopFrequency", String.format("%7.1f", loopFrequency));
-        return properties;
-    }
-
     public int nextEndIndex() {
         return nextEndIndex++;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -32,6 +32,7 @@
  * The {@code PhiNode} represents the merging of dataflow in the graph. It refers to a merge
  * and a variable.
  */
+@NodeInfo(nameTemplate = "{p#type/s}Phi({i#values})")
 public final class PhiNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType {
 
     public static enum PhiType {
@@ -80,6 +81,11 @@
         return merge;
     }
 
+    public void setMerge(MergeNode x) {
+        updateUsages(merge, x);
+        merge = x;
+    }
+
     public NodeInputList<ValueNode> values() {
         return values;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -50,4 +50,17 @@
     public void generate(LIRGeneratorTool generator) {
         generator.setResult(this, generator.operand(object));
     }
+
+    @Override
+    public boolean inferStamp() {
+        if (object().stamp().nonNull() && !stamp().nonNull()) {
+            setStamp(StampFactory.declaredNonNull(objectStamp().type()));
+            return true;
+        }
+        if (object().objectStamp().alwaysNull() && !objectStamp().alwaysNull()) {
+            setStamp(StampFactory.alwaysNull());
+            return true;
+        }
+        return super.inferStamp();
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import java.util.*;
-
 import com.oracle.graal.graph.*;
 
 public abstract class ScheduledNode extends Node {
@@ -38,17 +36,4 @@
         updatePredecessor(scheduledNext, x);
         scheduledNext = x;
     }
-
-    @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> debugProperties = super.getDebugProperties();
-        if (this instanceof StateSplit) {
-            StateSplit stateSplit = (StateSplit) this;
-            if (stateSplit.stateAfter() != null) {
-                debugProperties.put("stateAfter", stateSplit.stateAfter().toString(Verbosity.Debugger));
-            }
-        }
-        return debugProperties;
-    }
-
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -22,9 +22,11 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.nodes.extended.*;
+
 /**
  * The start node of a graph.
  */
-public class StartNode extends BeginStateSplitNode {
+public class StartNode extends BeginStateSplitNode implements MemoryCheckpoint{
 
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -55,19 +55,16 @@
     public ValueNode(Stamp stamp) {
         this.stamp = stamp;
         this.dependencies = new NodeInputList<>(this);
-        assert kind() != null && kind() == kind().stackKind() : kind() + " != " + kind().stackKind();
     }
 
     public ValueNode(Stamp stamp, ValueNode... dependencies) {
         this.stamp = stamp;
         this.dependencies = new NodeInputList<>(this, dependencies);
-        assert kind() != null && kind() == kind().stackKind() : kind() + " != " + kind().stackKind();
     }
 
     public ValueNode(Stamp stamp, List<ValueNode> dependencies) {
         this.stamp = stamp;
         this.dependencies = new NodeInputList<>(this, dependencies);
-        assert kind() != null && kind() == kind().stackKind() : kind() + " != " + kind().stackKind();
     }
 
     public Stamp stamp() {
@@ -176,12 +173,14 @@
         for (ValueNode v : dependencies().nonNull()) {
             assertTrue(!(v.stamp() instanceof GenericStamp) || ((GenericStamp) v.stamp()).type() == GenericStampType.Dependency, "cannot depend on node with stamp %s", v.stamp());
         }
+        assertTrue(kind() != null, "Should have a valid kind");
+        assertTrue(kind() == kind().stackKind(), "Should have a stack kind : %s", kind());
         return super.verify();
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> properties = super.getDebugProperties();
+    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+        Map<Object, Object> properties = super.getDebugProperties(map);
         if (!dependencies.isEmpty()) {
             StringBuilder str = new StringBuilder();
             for (int i = 0; i < dependencies.size(); i++) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/Condition.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/Condition.java	Wed Jul 18 10:50:57 2012 -0700
@@ -240,9 +240,10 @@
 
     /**
      * Attempts to fold a comparison between two constants and return the result.
+     *
      * @param lt the constant on the left side of the comparison
      * @param rt the constant on the right side of the comparison
-     * @param runtime the RiRuntime (might be needed to compare runtime-specific types)
+     * @param runtime needed to compare runtime-specific types
      * @return {@link Boolean#TRUE} if the comparison is known to be true,
      * {@link Boolean#FALSE} if the comparison is known to be false
      */
@@ -253,9 +254,10 @@
 
     /**
      * Attempts to fold a comparison between two constants and return the result.
+     *
      * @param lt the constant on the left side of the comparison
      * @param rt the constant on the right side of the comparison
-     * @param runtime the RiRuntime (might be needed to compare runtime-specific types)
+     * @param runtime needed to compare runtime-specific types
      * @param unorderedIsTrue true if an undecided float comparison should result in "true"
      * @return true if the comparison is known to be true, false if the comparison is known to be false
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -45,7 +45,7 @@
      */
     public IsNullNode(ValueNode object) {
         super(StampFactory.condition());
-        assert object.kind() == Kind.Object : object.kind();
+        assert object.kind() == Kind.Object : object;
         this.object = object;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -58,9 +58,9 @@
             return ConstantNode.forBoolean(true, graph());
         }
 
-        if (x().isNullConstant()) {
+        if (x().objectStamp().alwaysNull()) {
             return graph().unique(new IsNullNode(y()));
-        } else if (y().isNullConstant()) {
+        } else if (y().objectStamp().alwaysNull()) {
             return graph().unique(new IsNullNode(x()));
         }
         if (x().stamp().alwaysDistinct(y().stamp())) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Wed Jul 18 10:50:57 2012 -0700
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
 public interface Access {
@@ -31,4 +32,6 @@
     LocationNode location();
 
     void setNullCheck(boolean check);
+
+    Node node();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -22,9 +22,15 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
+/**
+ * Accesses a value at an memory address specified by an {@linkplain #object object}
+ * and a {@linkplain #location() location}. The access does not include a null check
+ * on the object.
+ */
 public abstract class AccessNode extends FixedWithNextNode implements Access {
 
     @Input private ValueNode object;
@@ -52,4 +58,9 @@
         this.object = object;
         this.location = location;
     }
+
+    @Override
+    public Node node() {
+        return this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.type.*;
@@ -67,4 +68,9 @@
         this.object = object;
         this.location = location;
     }
+
+    @Override
+    public Node node() {
+        return this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,7 +33,7 @@
  * A floating read of a value from memory specified in terms of an object base and an object relative location.
  * This node does not null check the object.
  */
-public final class FloatingReadNode extends FloatingAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable {
+public final class FloatingReadNode extends FloatingAccessNode implements Node.IterableNodeType, LIRLowerable/*, Canonicalizable*/ {
 
     @Input private Node lastLocationAccess;
 
@@ -57,20 +56,9 @@
         gen.setResult(this, gen.emitLoad(gen.makeAddress(location(), object()), getNullCheck()));
     }
 
-    @Override
+    // Canonicalization disabled untill we have a solution for non-Object oops in Hotspot
+    /*@Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        MetaAccessProvider runtime = tool.runtime();
-        if (runtime != null && object() != null && object().isConstant() && object().kind() == Kind.Object) {
-            if (this.location() == LocationNode.FINAL_LOCATION && location().getClass() == LocationNode.class) {
-                Object value = object().asConstant().asObject();
-                long displacement = location().displacement();
-                Kind kind = location().kind();
-                Constant constant = kind.readUnsafeConstant(value, displacement);
-                if (constant != null) {
-                    return ConstantNode.forConstant(constant, runtime, graph());
-                }
-            }
-        }
-        return this;
-    }
+        return ReadNode.canonicalizeRead(this, tool);
+    }*/
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -33,18 +33,27 @@
  * A location for a memory access in terms of the kind of value accessed and the displacement
  * (in bytes) from a base object or address.
  */
+@NodeInfo(nameTemplate = "Loc {p#locationIdentity/s}")
 public class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable {
 
     private int displacement;
     private Kind valueKind;
     private Object locationIdentity;
 
+    /**
+     * Denotes any location. A write to such a location kills all values in a memory map
+     * during an analysis of memory accesses in a graph.
+     */
     public static final Object ANY_LOCATION = new Object() {
         @Override
         public String toString() {
             return "ANY_LOCATION";
         }
     };
+
+    /**
+     * Denotes the location of a value that is guaranteed to be final.
+     */
     public static final Object FINAL_LOCATION = new Object() {
         @Override
         public String toString() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -28,8 +28,10 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-
-public final class ReadNode extends AccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable {
+/**
+ * Reads an {@linkplain AccessNode accessed} value.
+ */
+public final class ReadNode extends AccessNode implements Node.IterableNodeType, LIRLowerable/*, Canonicalizable*/ {
 
     public ReadNode(ValueNode object, LocationNode location, Stamp stamp) {
         super(object, location, stamp);
@@ -40,20 +42,26 @@
         gen.setResult(this, gen.emitLoad(gen.makeAddress(location(), object()), getNullCheck()));
     }
 
-    @Override
+    // Canonicalization disabled untill we have a solution for non-Object oops in Hotspot
+    /*@Override
     public ValueNode canonical(CanonicalizerTool tool) {
+        return canonicalizeRead(this, tool);
+    }*/
+
+    public static ValueNode canonicalizeRead(Access read, CanonicalizerTool tool) {
         MetaAccessProvider runtime = tool.runtime();
-        if (runtime != null && object() != null && object().isConstant() && object().kind() == Kind.Object) {
-            if (location() == LocationNode.FINAL_LOCATION && location().getClass() == LocationNode.class) {
-                Object value = object().asConstant().asObject();
-                long displacement = location().displacement();
-                Kind kind = location().kind();
+        if (runtime != null && read.object() != null && read.object().isConstant() && read.object().kind() == Kind.Object) {
+            if (read.location().locationIdentity() == LocationNode.FINAL_LOCATION && read.location().getClass() == LocationNode.class) {
+                Object value = read.object().asConstant().asObject();
+                long displacement = read.location().displacement();
+                Kind kind = read.location().getValueKind();
                 Constant constant = kind.readUnsafeConstant(value, displacement);
                 if (constant != null) {
-                    return ConstantNode.forConstant(constant, runtime, graph());
+                    System.out.println("Canon read to " + constant);
+                    return ConstantNode.forConstant(constant, runtime, read.node().graph());
                 }
             }
         }
-        return this;
+        return (ValueNode) read;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -23,10 +23,12 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
+@NodeInfo(nameTemplate = "RuntimeCall#{p#call/s}")
 public final class RuntimeCallNode extends AbstractCallNode implements LIRLowerable {
 
     private final RuntimeCall call;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -26,6 +26,10 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
+/**
+ * An analog to {@link ReadNode} with the additional semantics of null-checking
+ * the receiver object before reading from it.
+ */
 public class SafeReadNode extends SafeAccessNode implements Lowerable {
 
     public SafeReadNode(ValueNode object, LocationNode location, Stamp stamp, long leafGraphId) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -26,6 +26,10 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
+/**
+ * An analog to {@link WriteNode} with the additional semantics of null-checking
+ * the receiver object before writing to it.
+ */
 public class SafeWriteNode extends SafeAccessNode implements StateSplit, Lowerable {
 
     @Input private ValueNode value;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -41,7 +41,7 @@
     }
 
     public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
-        super(toType.kind().isObject() ? new ObjectStamp(toType, exactType, nonNull) : StampFactory.forKind(toType.kind()));
+        super(toType.kind().isObject() ? new ObjectStamp(toType, exactType, nonNull, false) : StampFactory.forKind(toType.kind()));
         this.object = object;
         this.toType = toType;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -37,7 +37,7 @@
 public final class ValueAnchorNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType {
 
     public ValueAnchorNode(ValueNode... values) {
-        super(StampFactory.forVoid(), values);
+        super(StampFactory.dependency(), values);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -27,6 +27,9 @@
 import com.oracle.graal.nodes.type.*;
 
 
+/**
+ * Writes a given {@linkplain #value() value} a {@linkplain AccessNode memory location}.
+ */
 public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable {
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.java;
 
 import java.lang.reflect.*;
-import java.util.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
@@ -91,13 +90,6 @@
     }
 
     @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> debugProperties = super.getDebugProperties();
-        debugProperties.put("field", MetaUtil.format("%h.%n", field));
-        return debugProperties;
-    }
-
-    @Override
     public String toString(Verbosity verbosity) {
         if (verbosity == Verbosity.Name) {
             return super.toString(verbosity) + "#" + field.name();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -51,7 +51,7 @@
     }
 
     public CheckCastNode(ValueNode targetClassInstruction, ResolvedJavaType targetClass, ValueNode object, JavaTypeProfile profile) {
-        super(targetClass == null ? StampFactory.forKind(Kind.Object) : StampFactory.declared(targetClass));
+        super(targetClass == null ? StampFactory.object() : StampFactory.declared(targetClass));
         this.targetClassInstruction = targetClassInstruction;
         this.targetClass = targetClass;
         this.object = object;
@@ -69,6 +69,15 @@
     }
 
     @Override
+    public boolean inferStamp() {
+        if (object().stamp().nonNull() && !stamp().nonNull()) {
+            setStamp(targetClass == null ? StampFactory.objectNonNull() : StampFactory.declaredNonNull(targetClass));
+            return true;
+        }
+        return super.inferStamp();
+    }
+
+    @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         assert object() != null : this;
 
@@ -80,12 +89,8 @@
             }
         }
 
-        Constant constant = object().asConstant();
-        if (constant != null) {
-            assert constant.kind == Kind.Object;
-            if (constant.isNull()) {
-                return object();
-            }
+        if (object().objectStamp().alwaysNull()) {
+            return object();
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -103,15 +103,8 @@
                 // since the subtype comparison was only performed on a declared type we don't really know if it might be true at run time...
             }
         }
-
-        Constant constant = object().asConstant();
-        if (constant != null) {
-            assert constant.kind == Kind.Object;
-            if (constant.isNull()) {
-                return ConstantNode.forBoolean(false, graph());
-            } else {
-                assert false : "non-null constants are always expected to provide an exact type";
-            }
+        if (object().objectStamp().alwaysNull()) {
+            return ConstantNode.forBoolean(false, graph());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -31,6 +31,7 @@
 /**
  * The {@code LoadFieldNode} represents a read of a static or instance field.
  */
+@NodeInfo(nameTemplate = "LoadField#{p#field/s}")
 public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable, Node.IterableNodeType {
 
     /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -39,6 +39,7 @@
 public abstract class NewArrayNode extends FixedWithNextNode implements Lowerable, EscapeAnalyzable, TypeFeedbackProvider {
 
     @Input private ValueNode length;
+    private final ResolvedJavaType elementType;
 
     public static final int MaximumEscapeAnalysisArrayLength = 32;
 
@@ -50,9 +51,10 @@
      * Constructs a new NewArrayNode.
      * @param length the node that produces the length for this allocation
      */
-    protected NewArrayNode(Stamp stamp, ValueNode length) {
-        super(stamp);
+    protected NewArrayNode(ResolvedJavaType elementType, ValueNode length) {
+        super(StampFactory.exactNonNull(elementType.arrayOf()));
         this.length = length;
+        this.elementType = elementType;
     }
 
     /**
@@ -64,18 +66,20 @@
     }
 
     /**
+     * Gets the element type of the array.
+     * @return the element type of the array
+     */
+    public ResolvedJavaType elementType() {
+        return elementType;
+    }
+
+    /**
      * The rank of the array allocated by this node, i.e. how many array dimensions.
      */
     public int dimensionCount() {
         return 1;
     }
 
-    /**
-     * Gets the element type of the array.
-     * @return the element type of the array
-     */
-    public abstract ResolvedJavaType elementType();
-
     @Override
     public void typeFeedback(TypeFeedbackTool tool) {
         assert length.kind() == Kind.Int;
@@ -130,12 +134,13 @@
                 AccessIndexedNode x = (AccessIndexedNode) current;
                 if (GraphUtil.unProxify(x.array()) == node) {
                     int index = ((AccessIndexedNode) current).index().asConstant().asInt();
+                    StructuredGraph graph = (StructuredGraph) x.graph();
                     if (current instanceof LoadIndexedNode) {
                         x.replaceAtUsages(fieldState[index]);
-                        ((StructuredGraph) x.graph()).removeFixed(x);
+                        graph.removeFixed(x);
                     } else if (current instanceof StoreIndexedNode) {
                         fieldState[index] = ((StoreIndexedNode) x).value();
-                        ((StructuredGraph) x.graph()).removeFixed(x);
+                        graph.removeFixed(x);
                         return index;
                     }
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -34,6 +34,7 @@
 /**
  * The {@code NewInstanceNode} represents the allocation of an instance class object.
  */
+@NodeInfo(nameTemplate = "New {p#instanceClass/s}")
 public final class NewInstanceNode extends FixedWithNextNode implements EscapeAnalyzable, Lowerable, LIRLowerable, Node.IterableNodeType {
 
     private final ResolvedJavaType instanceClass;
@@ -65,13 +66,6 @@
         gen.visitNewInstance(this);
     }
 
-    @Override
-    public Map<Object, Object> getDebugProperties() {
-        Map<Object, Object> properties = super.getDebugProperties();
-        properties.put("instanceClass", instanceClass);
-        return properties;
-    }
-
     public EscapeOp getEscapeOp() {
         return ESCAPE;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewObjectArrayNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewObjectArrayNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -26,28 +26,20 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code NewObjectArrayNode} represents an allocation of an object array.
  */
+@NodeInfo(nameTemplate = "NewArray {p#elementType}")
 public final class NewObjectArrayNode extends NewArrayNode implements LIRLowerable, Node.IterableNodeType {
 
-    private final ResolvedJavaType elementClass;
-
     /**
      * Constructs a new NewObjectArrayNode.
      * @param elementClass the class of elements in this array
      * @param length the node producing the length of the array
      */
     public NewObjectArrayNode(ResolvedJavaType elementClass, ValueNode length) {
-        super(StampFactory.exactNonNull(elementClass.arrayOf()), length);
-        this.elementClass = elementClass;
-    }
-
-    @Override
-    public ResolvedJavaType elementType() {
-        return elementClass;
+        super(elementClass, length);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewPrimitiveArrayNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewPrimitiveArrayNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -23,25 +23,18 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code NewPrimitiveArrayNode} class definition.
  */
+@NodeInfo(nameTemplate = "NewArray {p#elementType}")
 public final class NewPrimitiveArrayNode extends NewArrayNode implements LIRLowerable {
 
-    private final ResolvedJavaType elementType;
-
-    public NewPrimitiveArrayNode(ValueNode length, ResolvedJavaType elementType) {
-        super(StampFactory.exactNonNull(elementType.arrayOf()), length);
-        this.elementType = elementType;
-    }
-
-    @Override
-    public ResolvedJavaType elementType() {
-        return elementType;
+    public NewPrimitiveArrayNode(ResolvedJavaType elementType, ValueNode length) {
+        super(elementType, length);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -23,12 +23,14 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code StoreFieldNode} represents a write to a static or instance field.
  */
+@NodeInfo(nameTemplate = "StoreField#{p#field/s}")
 public final class StoreFieldNode extends AccessFieldNode implements StateSplit {
 
     @Input private ValueNode value;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java	Wed Jul 18 10:50:57 2012 -0700
@@ -37,7 +37,4 @@
     void lower(Node n, LoweringTool tool);
 
     StructuredGraph intrinsicGraph(ResolvedJavaMethod caller, int bci, ResolvedJavaMethod method, List<? extends Node> parameters);
-
-    CompilationResult compile(ResolvedJavaMethod method, StructuredGraph graph);
-
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ObjectTypeFeedbackStore.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ObjectTypeFeedbackStore.java	Wed Jul 18 10:50:57 2012 -0700
@@ -498,15 +498,15 @@
     /*
 //    equals contains all the values that might happen to be in this variable. If it is null then there is no information about possible values.
 //    If it is empty, then we're currently in a branch that will be removed by canonicalization later on.
-    private Set<CiConstant> equals;
+    private Set<Constant> equals;
 //    notEquals contains all the values that cannot be in this variable.
-    private Set<CiConstant> notEquals;
+    private Set<Constant> notEquals;
 
     private HashMap<ValueNode, Condition> valueBounds;
 
-    private Set<RiResolvedType> exactTypes;
+    private Set<ResolvedJavaType> exactTypes;
 
-    private Set<RiResolvedType> declaredTypes;
+    private Set<ResolvedJavaType> declaredTypes;
     private final TypeFeedbackChanged changed;
 
     private Node dependency;
@@ -536,7 +536,7 @@
     }
 
     @Override
-    public void constantBound(Condition condition, CiConstant constant) {
+    public void constantBound(Condition condition, Constant constant) {
         assert condition == Condition.EQ || condition == Condition.NE;
 
         if (condition == Condition.EQ) {
@@ -594,15 +594,15 @@
     }
 
     @Override
-    public void declaredType(RiResolvedType type, boolean nonNull) {
+    public void declaredType(ResolvedJavaType type, boolean nonNull) {
         if (declaredTypes == null) {
             declaredTypes = new HashSet<>();
             declaredTypes.add(type);
             updateDependency();
         } else {
             if (type.isInterface()) {
-                for (Iterator<RiResolvedType> iter = declaredTypes.iterator(); iter.hasNext();) {
-                    RiResolvedType declaredType = iter.next();
+                for (Iterator<ResolvedJavaType> iter = declaredTypes.iterator(); iter.hasNext();) {
+                    ResolvedJavaType declaredType = iter.next();
                     if (declaredType.isInterface()) {
                         if (type.isSubtypeOf(declaredType)) {
                             iter.remove();
@@ -616,8 +616,8 @@
                     updateDependency();
                 }
             } else {
-                for (Iterator<RiResolvedType> iter = declaredTypes.iterator(); iter.hasNext();) {
-                    RiResolvedType declaredType = iter.next();
+                for (Iterator<ResolvedJavaType> iter = declaredTypes.iterator(); iter.hasNext();) {
+                    ResolvedJavaType declaredType = iter.next();
                     if (!declaredType.isInterface()) {
                         if (type.isSubtypeOf(declaredType)) {
                             iter.remove();
@@ -633,12 +633,12 @@
             }
         }
         if (nonNull) {
-            constantBound(Condition.NE, CiConstant.NULL_OBJECT);
+            constantBound(Condition.NE, Constant.NULL_OBJECT);
         }
     }
 
     @Override
-    public void exactType(RiResolvedType type) {
+    public void exactType(ResolvedJavaType type) {
         if (exactTypes == null) {
             exactTypes = new HashSet<>();
             exactTypes.add(type);
@@ -653,15 +653,15 @@
                 exactTypes.clear();
             }
         }
-        constantBound(Condition.NE, CiConstant.NULL_OBJECT);
+        constantBound(Condition.NE, Constant.NULL_OBJECT);
     }
 
     @Override
-    public void notDeclaredType(RiResolvedType type, boolean nonNull) {
+    public void notDeclaredType(ResolvedJavaType type, boolean nonNull) {
     }
 
     @Override
-    public void notExactType(RiResolvedType type) {
+    public void notExactType(ResolvedJavaType type) {
     }
 
     @Override
@@ -673,8 +673,8 @@
             equals = null;
         }
         if (notEquals != null && !notEquals.isEmpty() && other.notEquals != null && !other.notEquals.isEmpty()) {
-            for (Iterator<CiConstant> iter = notEquals.iterator(); iter.hasNext();) {
-                CiConstant constant = iter.next();
+            for (Iterator<Constant> iter = notEquals.iterator(); iter.hasNext();) {
+                Constant constant = iter.next();
                 if (!other.notEquals.contains(constant)) {
                     iter.remove();
                 }
@@ -727,7 +727,7 @@
                 str.append(equals.iterator().next());
             } else {
                 str.append("(");
-                for (CiConstant constant : equals) {
+                for (Constant constant : equals) {
                     str.append(constant).append(',');
                 }
                 str.setLength(str.length() - 1);
@@ -741,7 +741,7 @@
                 str.append(notEquals.iterator().next());
             } else {
                 str.append("(");
-                for (CiConstant constant : notEquals) {
+                for (Constant constant : notEquals) {
                     str.append(constant).append(',');
                 }
                 str.setLength(str.length() - 1);
@@ -756,7 +756,7 @@
         }
         if (declaredTypes != null) {
             str.append("declared (");
-            for (RiResolvedType type: declaredTypes) {
+            for (ResolvedJavaType type: declaredTypes) {
                 str.append(type).append(',');
             }
             str.setLength(str.length() - 1);
@@ -764,7 +764,7 @@
         }
         if (exactTypes != null) {
             str.append("exact (");
-            for (RiResolvedType type: exactTypes) {
+            for (ResolvedJavaType type: exactTypes) {
                 str.append(type).append(',');
             }
             str.setLength(str.length() - 1);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java	Wed Jul 18 10:50:57 2012 -0700
@@ -27,25 +27,116 @@
 
 public class FloatStamp extends Stamp {
 
+    private final double lowerBound;
+    private final double upperBound;
+    private final boolean nonNaN;
+
     protected FloatStamp(Kind kind) {
+        this(kind, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, false);
+        assert kind == Kind.Float || kind == Kind.Double;
+    }
+
+    protected FloatStamp(Kind kind, double lowerBound, double upperBound, boolean nonNaN) {
         super(kind);
-        assert kind == Kind.Float || kind == Kind.Double;
+        assert (!nonNaN && Double.isNaN(lowerBound) && Double.isNaN(upperBound)) || lowerBound <= upperBound;
+        this.lowerBound = lowerBound;
+        this.upperBound = upperBound;
+        this.nonNaN = nonNaN;
+    }
+
+    /**
+     * The (inclusive) lower bound on the value described by this stamp.
+     */
+    public double lowerBound() {
+        return lowerBound;
+    }
+
+    /**
+     * The (inclusive) upper bound on the value described by this stamp.
+     */
+    public double upperBound() {
+        return upperBound;
+    }
+
+    public boolean isUnrestricted() {
+        return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN;
+    }
+
+    public boolean contains(double value) {
+        if (Double.isNaN(value)) {
+            return !nonNaN;
+        } else {
+            return value >= lowerBound && value <= upperBound;
+        }
     }
 
     @Override
     public String toString() {
-        return "" + kind().typeChar;
+        StringBuilder str = new StringBuilder();
+        str.append(kind().typeChar);
+        str.append(nonNaN ? "!" : "");
+        if (lowerBound == upperBound) {
+            str.append(" [").append(lowerBound).append(']');
+        } else if (lowerBound != Double.NEGATIVE_INFINITY || upperBound != Double.POSITIVE_INFINITY) {
+            str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']');
+        }
+        return str.toString();
+    }
+
+    @Override
+    public boolean alwaysDistinct(Stamp otherStamp) {
+        FloatStamp other = (FloatStamp) otherStamp;
+        return (nonNaN || other.nonNaN) && (lowerBound > other.upperBound || upperBound < other.lowerBound);
+    }
+
+    @Override
+    public Stamp meet(Stamp otherStamp) {
+        FloatStamp other = (FloatStamp) otherStamp;
+        assert kind() == other.kind();
+        double meetUpperBound = Math.max(upperBound, other.upperBound);
+        double meetLowerBound = Math.min(lowerBound, other.lowerBound);
+        boolean meetNonNaN = nonNaN && other.nonNaN;
+        if (meetLowerBound == lowerBound && meetUpperBound == upperBound && meetNonNaN == nonNaN) {
+            return this;
+        } else if (meetLowerBound == other.lowerBound && meetUpperBound == other.upperBound && meetNonNaN == other.nonNaN) {
+            return other;
+        } else {
+            return new FloatStamp(kind(), meetLowerBound, meetUpperBound, meetNonNaN);
+        }
     }
 
     @Override
-    public boolean alwaysDistinct(Stamp other) {
-        return false;
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        long temp;
+        temp = Double.doubleToLongBits(lowerBound);
+        result = prime * result + (int) (temp ^ (temp >>> 32));
+        result = prime * result + (nonNaN ? 1231 : 1237);
+        temp = Double.doubleToLongBits(upperBound);
+        result = prime * result + (int) (temp ^ (temp >>> 32));
+        return result;
     }
 
     @Override
-    public Stamp meet(Stamp other) {
-        assert kind() == other.kind();
-        return this;
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        FloatStamp other = (FloatStamp) obj;
+        if (Double.doubleToLongBits(lowerBound) != Double.doubleToLongBits(other.lowerBound)) {
+            return false;
+        }
+        if (Double.doubleToLongBits(upperBound) != Double.doubleToLongBits(other.upperBound)) {
+            return false;
+        }
+        if (nonNaN != other.nonNaN) {
+            return false;
+        }
+        return true;
     }
 
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Wed Jul 18 10:50:57 2012 -0700
@@ -111,6 +111,8 @@
         long meetMask = mask | other.mask;
         if (meetLowerBound == lowerBound && meetUpperBound == upperBound && meetMask == mask) {
             return this;
+        } else if (meetLowerBound == other.lowerBound && meetUpperBound == other.upperBound && meetMask == other.mask) {
+            return other;
         } else {
             return new IntegerStamp(kind(), meetLowerBound, meetUpperBound, meetMask);
         }
@@ -122,6 +124,7 @@
         int result = 1;
         result = prime * result + (int) (lowerBound ^ (lowerBound >>> 32));
         result = prime * result + (int) (upperBound ^ (upperBound >>> 32));
+        result = prime * result + (int) (mask ^ (mask >>> 32));
         return result;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Wed Jul 18 10:50:57 2012 -0700
@@ -30,13 +30,16 @@
     private final ResolvedJavaType type;
     private final boolean exactType;
     private final boolean nonNull;
+    private final boolean alwaysNull;
 
-    public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull) {
+    public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) {
         super(Kind.Object);
         assert !exactType || type != null;
+        assert !(nonNull && alwaysNull);
         this.type = type;
         this.exactType = exactType;
         this.nonNull = nonNull;
+        this.alwaysNull = alwaysNull;
     }
 
     @Override
@@ -44,6 +47,10 @@
         return nonNull;
     }
 
+    public boolean alwaysNull() {
+        return alwaysNull;
+    }
+
     public ResolvedJavaType type() {
         return type;
     }
@@ -56,13 +63,16 @@
     public String toString() {
         StringBuilder str = new StringBuilder();
         str.append(kind().typeChar);
-        str.append(nonNull ? "!" : "").append(exactType ? "#" : "").append(' ').append(type == null ? "-" : type.name());
+        str.append(nonNull ? "!" : "").append(exactType ? "#" : "").append(' ').append(type == null ? "-" : type.name()).append(alwaysNull ? " NULL" : "");
         return str.toString();
     }
 
     @Override
     public boolean alwaysDistinct(Stamp otherStamp) {
         ObjectStamp other = (ObjectStamp) otherStamp;
+        if ((alwaysNull && other.nonNull) || (nonNull && other.alwaysNull)) {
+            return true;
+        }
         if (other.type == null || type == null) {
             // We have no type information for one of the values.
             return false;
@@ -76,14 +86,31 @@
     @Override
     public Stamp meet(Stamp otherStamp) {
         ObjectStamp other = (ObjectStamp) otherStamp;
-        ResolvedJavaType orType = meetTypes(type(), other.type());
-        boolean meetExactType = orType == type && orType == other.type && exactType && other.exactType;
-        boolean meetNonNull = nonNull && other.nonNull;
+        ResolvedJavaType meetType;
+        boolean meetExactType;
+        boolean meetNonNull;
+        boolean meetAlwaysNull;
+        if (other.alwaysNull) {
+            meetType = type();
+            meetExactType = exactType;
+            meetNonNull = false;
+            meetAlwaysNull = alwaysNull;
+        } else if (alwaysNull) {
+            meetType = other.type();
+            meetExactType = other.exactType;
+            meetNonNull = false;
+            meetAlwaysNull = other.alwaysNull;
+        } else {
+            meetType = meetTypes(type(), other.type());
+            meetExactType = meetType == type && meetType == other.type && exactType && other.exactType;
+            meetNonNull = nonNull && other.nonNull;
+            meetAlwaysNull = false;
+        }
 
-        if (orType == type && meetExactType == exactType && meetNonNull == nonNull) {
+        if (meetType == type && meetExactType == exactType && meetNonNull == nonNull && meetAlwaysNull == alwaysNull) {
             return this;
         } else {
-            return new ObjectStamp(orType, meetExactType, meetNonNull);
+            return new ObjectStamp(meetType, meetExactType, meetNonNull, meetAlwaysNull);
         }
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Wed Jul 18 10:50:57 2012 -0700
@@ -28,10 +28,10 @@
 
 
 public class StampFactory {
-
     private static final Stamp[] stampCache = new Stamp[Kind.values().length];
-    private static final Stamp objectStamp = new ObjectStamp(null, false, false);
-    private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true);
+    private static final Stamp objectStamp = new ObjectStamp(null, false, false, false);
+    private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true, false);
+    private static final Stamp objectAlwaysNullStamp = new ObjectStamp(null, false, false, true);
     private static final Stamp dependencyStamp = new GenericStamp(GenericStampType.Dependency);
     private static final Stamp extensionStamp = new GenericStamp(GenericStampType.Extension);
     private static final Stamp virtualStamp = new GenericStamp(GenericStampType.Virtual);
@@ -102,6 +102,10 @@
         return new IntegerStamp(kind, lowerBound, upperBound, mask);
     }
 
+    public static Stamp forFloat(Kind kind, double lowerBound, double upperBound, boolean nonNaN) {
+        return new FloatStamp(kind, lowerBound, upperBound, nonNaN);
+    }
+
     public static Stamp forConstant(Constant value) {
         assert value.kind != Kind.Object;
         if (value.kind == Kind.Object) {
@@ -109,6 +113,8 @@
         } else {
             if (value.kind == Kind.Int || value.kind == Kind.Long) {
                 return forInteger(value.kind, value.asLong(), value.asLong(), value.asLong() & IntegerStamp.defaultMask(value.kind));
+            } else if (value.kind == Kind.Float || value.kind == Kind.Double) {
+                return forFloat(value.kind, value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble()));
             }
             return forKind(value.kind.stackKind());
         }
@@ -118,9 +124,9 @@
         assert value.kind == Kind.Object;
         if (value.kind == Kind.Object) {
             ResolvedJavaType type = value.isNull() ? null : runtime.getTypeOf(value);
-            return new ObjectStamp(type, value.isNonNull(), value.isNonNull());
+            return new ObjectStamp(type, value.isNonNull(), value.isNonNull(), value.isNull());
         } else {
-            throw new GraalInternalError("CiKind.Object expected, actual kind: %s", value.kind);
+            throw new GraalInternalError(Kind.Object + " expected, actual kind: %s", value.kind);
         }
     }
 
@@ -132,6 +138,10 @@
         return objectNonNullStamp;
     }
 
+    public static Stamp alwaysNull() {
+        return objectAlwaysNullStamp;
+    }
+
     public static Stamp declared(ResolvedJavaType type) {
         return declared(type, false);
     }
@@ -145,13 +155,13 @@
         assert type.kind() == Kind.Object;
         ResolvedJavaType exact = type.exactType();
         if (exact != null) {
-            return new ObjectStamp(exact, true, nonNull);
+            return new ObjectStamp(exact, true, nonNull, false);
         } else {
-            return new ObjectStamp(type, false, nonNull);
+            return new ObjectStamp(type, false, nonNull, false);
         }
     }
 
     public static Stamp exactNonNull(ResolvedJavaType type) {
-        return new ObjectStamp(type, true, true);
+        return new ObjectStamp(type, true, true, false);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Wed Jul 18 10:50:57 2012 -0700
@@ -22,21 +22,24 @@
  */
 package com.oracle.graal.nodes.util;
 
-import static com.oracle.graal.graph.iterators.NodePredicates.*;
-
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.graph.iterators.NodePredicates.PositiveTypePredicate;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
 
 public class GraphUtil {
 
-    private static final PositiveTypePredicate FLOATING = isA(FloatingNode.class).or(VirtualState.class).or(CallTargetNode.class);
+    private static final NodePredicate FLOATING = new NodePredicate() {
+        @Override
+        public final boolean  apply(Node n) {
+            //isA(FloatingNode.class).or(VirtualState.class).or(CallTargetNode.class)
+            return n instanceof FloatingNode || n instanceof VirtualState || n instanceof CallTargetNode;
+        }
+    };
 
     public static void killCFG(FixedNode node) {
         assert node.isAlive();
@@ -219,4 +222,23 @@
         }
         return v;
     }
+
+    /**
+     * Returns a string representation of the given collection of objects.
+     *
+     * @param objects The {@link Iterable} that will be used to iterate over the objects.
+     * @return A string of the format "[a, b, ...]".
+     */
+    public static String toString(Iterable< ? > objects) {
+        StringBuilder str = new StringBuilder();
+        str.append("[");
+        for (Object o : objects) {
+            str.append(o).append(", ");
+        }
+        if (str.length() > 1) {
+            str.setLength(str.length() - 2);
+        }
+        str.append("]");
+        return str.toString();
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -23,10 +23,11 @@
 package com.oracle.graal.nodes.virtual;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-
+@NodeInfo(nameTemplate = "VirtualObject {p#type}")
 public class VirtualObjectNode extends FloatingNode implements LIRLowerable {
 
     private ResolvedJavaType type;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java	Wed Jul 18 10:50:57 2012 -0700
@@ -85,7 +85,13 @@
      */
     protected BasicIdealGraphPrinter(OutputStream stream) {
         try {
-            this.stream = new PrintStream(stream, false, "US-ASCII");
+            OutputStream buffered;
+            if (stream instanceof BufferedOutputStream) {
+                buffered = stream;
+            } else {
+                buffered = new BufferedOutputStream(stream, 256 * 1024);
+            }
+            this.stream = new PrintStream(buffered, false, "US-ASCII");
         } catch (UnsupportedEncodingException e) {
             throw new RuntimeException(e);
         }
@@ -251,7 +257,7 @@
     /**
      * Ends the current group.
      */
-    protected void endGroup() {
+    public void endGroup() {
         stream.println("</group>");
     }
 
@@ -263,6 +269,10 @@
         flush();
     }
 
+    public void close() {
+        end();
+        stream.close();
+    }
 
     public boolean isValid() {
         return !stream.checkError();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,438 @@
+/*
+ * 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.printer;
+
+import java.io.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.schedule.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.NodeClass.NodeClassIterator;
+import com.oracle.graal.graph.NodeClass.Position;
+import com.oracle.graal.lir.cfg.*;
+import com.oracle.graal.nodes.*;
+
+public class BinaryGraphPrinter implements GraphPrinter{
+    private static final int CONSTANT_POOL_MAX_SIZE = 2000;
+
+    private static final int BEGIN_GROUP = 0x00;
+    private static final int BEGIN_GRAPH = 0x01;
+    private static final int CLOSE_GROUP = 0x02;
+
+    private static final int POOL_NEW = 0x00;
+    private static final int POOL_STRING = 0x01;
+    private static final int POOL_ENUM = 0x02;
+    private static final int POOL_CLASS = 0x03;
+    private static final int POOL_METHOD = 0x04;
+    private static final int POOL_NULL = 0x05;
+    private static final int POOL_NODE_CLASS = 0x06;
+    private static final int POOL_FIELD = 0x07;
+    private static final int POOL_SIGNATURE = 0x08;
+
+    private static final int PROPERTY_POOL = 0x00;
+    private static final int PROPERTY_INT = 0x01;
+    private static final int PROPERTY_LONG = 0x02;
+    private static final int PROPERTY_DOUBLE = 0x03;
+    private static final int PROPERTY_FLOAT = 0x04;
+    private static final int PROPERTY_TRUE = 0x05;
+    private static final int PROPERTY_FALSE = 0x06;
+    private static final int PROPERTY_ARRAY = 0x07;
+
+    private static final int KLASS = 0x00;
+    private static final int ENUM_KLASS = 0x01;
+
+    private static final class ConstantPool extends LinkedHashMap<Object, Integer> {
+        private final LinkedList<Integer> availableIds;
+        private int nextId;
+        private static final long serialVersionUID = -2676889957907285681L;
+        public ConstantPool() {
+            super(50, 0.65f);
+            availableIds = new LinkedList<>();
+        }
+        @Override
+        protected boolean removeEldestEntry(java.util.Map.Entry<Object, Integer> eldest) {
+            if (size() > CONSTANT_POOL_MAX_SIZE) {
+                availableIds.addFirst(eldest.getValue());
+                return true;
+            }
+            return false;
+        }
+
+        private Integer nextAvailableId() {
+            if (!availableIds.isEmpty()) {
+                return availableIds.removeFirst();
+            }
+            return nextId++;
+        }
+
+        public int add(Object obj) {
+            Integer id = nextAvailableId();
+            put(obj, id);
+            return id;
+        }
+    }
+
+    private final ConstantPool constantPool;
+    private final ByteBuffer buffer;
+    private final WritableByteChannel channel;
+
+    public BinaryGraphPrinter(WritableByteChannel channel) {
+        constantPool = new ConstantPool();
+        buffer = ByteBuffer.allocateDirect(256 * 1024);
+        this.channel = channel;
+    }
+
+    public void print(Graph graph, String title, SchedulePhase predefinedSchedule) throws IOException {
+        SchedulePhase schedule = predefinedSchedule;
+        if (schedule == null) {
+            try {
+                schedule = new SchedulePhase();
+                schedule.apply((StructuredGraph) graph);
+            } catch (Throwable t) {
+            }
+        }
+        ControlFlowGraph cfg =  schedule == null ? null : schedule.getCFG();
+        BlockMap<List<ScheduledNode>> blockToNodes = schedule == null ? null : schedule.getBlockToNodesMap();
+        Block[] blocks = cfg == null ? null : cfg.getBlocks();
+        writeByte(BEGIN_GRAPH);
+        writePoolObject(title);
+        writeNodes(graph);
+        writeBlocks(blocks, blockToNodes);
+        flush();
+    }
+
+    private void flush() throws IOException {
+        buffer.flip();
+        channel.write(buffer);
+        buffer.compact();
+    }
+
+    private void ensureAvailable(int i) throws IOException {
+        while (buffer.remaining() < i) {
+            flush();
+        }
+    }
+
+    private void writeByte(int b) throws IOException {
+        ensureAvailable(1);
+        buffer.put((byte) b);
+    }
+
+    private void writeInt(int b) throws IOException {
+        ensureAvailable(4);
+        buffer.putInt(b);
+    }
+
+    private void writeLong(long b) throws IOException {
+        ensureAvailable(8);
+        buffer.putLong(b);
+    }
+
+    private void writeDouble(double b) throws IOException {
+        ensureAvailable(8);
+        buffer.putDouble(b);
+    }
+
+    private void writeFloat(float b) throws IOException {
+        ensureAvailable(4);
+        buffer.putFloat(b);
+    }
+
+    private void writeShort(char b) throws IOException {
+        ensureAvailable(2);
+        buffer.putChar(b);
+    }
+
+    private void writeString(String str) throws IOException {
+        writeInt(str.length());
+        ensureAvailable(str.length() * 2);
+        for (int i = 0; i < str.length(); i++) {
+            buffer.putChar(str.charAt(i));
+        }
+    }
+
+    private void writeBytes(byte[] b) throws IOException {
+        if (b == null) {
+            writeInt(-1);
+        } else {
+            writeInt(b.length);
+            ensureAvailable(b.length);
+            buffer.put(b);
+        }
+    }
+
+    private void writeInts(int[] b) throws IOException {
+        if (b == null) {
+            writeInt(-1);
+        } else {
+            writeInt(b.length);
+            ensureAvailable(b.length * 4);
+            for (int i = 0; i < b.length; i++) {
+                buffer.putInt(b[i]);
+            }
+        }
+    }
+
+    private void writeDoubles(double[] b) throws IOException {
+        if (b == null) {
+            writeInt(-1);
+        } else {
+            writeInt(b.length);
+            ensureAvailable(b.length * 8);
+            for (int i = 0; i < b.length; i++) {
+                buffer.putDouble(b[i]);
+            }
+        }
+    }
+
+    private void writePoolObject(Object object) throws IOException {
+        if (object == null) {
+            writeByte(POOL_NULL);
+            return;
+        }
+        if (object instanceof ResolvedJavaType) {
+            writePoolObject(((ResolvedJavaType) object).toJava());
+            return;
+        }
+        Integer id = constantPool.get(object);
+        if (id == null) {
+            addPoolEntry(object);
+        } else {
+            if (object instanceof Enum<?>) {
+                writeByte(POOL_ENUM);
+            } else if (object instanceof Class<?>) {
+                writeByte(POOL_CLASS);
+            } else if (object instanceof NodeClass) {
+                writeByte(POOL_NODE_CLASS);
+            } else if (object instanceof ResolvedJavaMethod) {
+                writeByte(POOL_METHOD);
+            } else if (object instanceof ResolvedJavaField) {
+                writeByte(POOL_FIELD);
+            } else if (object instanceof Signature) {
+                writeByte(POOL_SIGNATURE);
+            } else {
+                writeByte(POOL_STRING);
+            }
+            writeInt(id.intValue());
+        }
+    }
+
+    private void addPoolEntry(Object object) throws IOException {
+        int index = constantPool.add(object);
+        writeByte(POOL_NEW);
+        writeInt(index);
+        if (object instanceof Class<?>) {
+            Class<?> klass = (Class< ? >) object;
+            writeByte(POOL_CLASS);
+            writeString(klass.getName());
+            if (klass.isEnum()) {
+                writeByte(ENUM_KLASS);
+                Object[] enumConstants = klass.getEnumConstants();
+                writeInt(enumConstants.length);
+                for (Object o : enumConstants) {
+                    writePoolObject(((Enum<?>) o).name());
+                }
+            } else {
+                writeByte(KLASS);
+            }
+        } else if (object instanceof Enum<?>) {
+            writeByte(POOL_ENUM);
+            writePoolObject(object.getClass());
+            writeInt(((Enum) object).ordinal());
+        } else if (object instanceof NodeClass) {
+            NodeClass nodeClass = (NodeClass) object;
+            writeByte(POOL_NODE_CLASS);
+            writeString(nodeClass.getJavaClass().getSimpleName());
+            writeString(nodeClass.getNameTemplate());
+            List<Position> directInputPositions = nodeClass.getFirstLevelInputPositions();
+            writeShort((char) directInputPositions.size());
+            for (Position pos : directInputPositions) {
+                writePoolObject(nodeClass.getName(pos));
+            }
+            List<Position> directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions();
+            writeShort((char) directSuccessorPositions.size());
+            for (Position pos : directSuccessorPositions) {
+                writePoolObject(nodeClass.getName(pos));
+            }
+        } else if (object instanceof ResolvedJavaMethod) {
+            writeByte(POOL_METHOD);
+            ResolvedJavaMethod method = ((ResolvedJavaMethod) object);
+            writePoolObject(method.holder());
+            writePoolObject(method.name());
+            writePoolObject(method.signature());
+            writeInt(method.accessFlags());
+            writeBytes(method.code());
+        } else if (object instanceof ResolvedJavaField) {
+            writeByte(POOL_FIELD);
+            ResolvedJavaField field = ((ResolvedJavaField) object);
+            writePoolObject(field.holder());
+            writePoolObject(field.name());
+            writePoolObject(field.type().name());
+            writeInt(field.accessFlags());
+        } else if (object instanceof Signature) {
+            writeByte(POOL_SIGNATURE);
+            Signature signature = ((Signature) object);
+            int args = signature.argumentCount(false);
+            writeShort((char) args);
+            for (int i = 0; i < args; i++) {
+                writePoolObject(signature.argumentTypeAt(i, null).name());
+            }
+            writePoolObject(signature.returnType(null).name());
+        } else {
+            writeByte(POOL_STRING);
+            writeString(object.toString());
+        }
+    }
+
+    private void writePropertyObject(Object obj) throws IOException {
+        if (obj instanceof Integer) {
+            writeByte(PROPERTY_INT);
+            writeInt(((Integer) obj).intValue());
+        } else if (obj instanceof Long) {
+            writeByte(PROPERTY_LONG);
+            writeLong(((Long) obj).longValue());
+        } else if (obj instanceof Double) {
+            writeByte(PROPERTY_DOUBLE);
+            writeDouble(((Double) obj).doubleValue());
+        } else if (obj instanceof Float) {
+            writeByte(PROPERTY_FLOAT);
+            writeFloat(((Float) obj).floatValue());
+        } else if (obj instanceof Boolean) {
+            if (((Boolean) obj).booleanValue()) {
+                writeByte(PROPERTY_TRUE);
+            } else {
+                writeByte(PROPERTY_FALSE);
+            }
+        } else if (obj != null && obj.getClass().isArray()) {
+            Class< ? > componentType = obj.getClass().getComponentType();
+            if (componentType.isPrimitive()) {
+                if (componentType == Double.TYPE) {
+                    writeByte(PROPERTY_ARRAY);
+                    writeByte(PROPERTY_DOUBLE);
+                    writeDoubles((double[]) obj);
+                } else if (componentType == Integer.TYPE) {
+                    writeByte(PROPERTY_ARRAY);
+                    writeByte(PROPERTY_INT);
+                    writeInts((int[]) obj);
+                } else {
+                    writeByte(PROPERTY_POOL);
+                    writePoolObject(obj);
+                }
+            } else {
+                writeByte(PROPERTY_ARRAY);
+                writeByte(PROPERTY_POOL);
+                Object[] array = (Object[]) obj;
+                writeInt(array.length);
+                for (Object o : array) {
+                    writePoolObject(o);
+                }
+            }
+        } else {
+            writeByte(PROPERTY_POOL);
+            writePoolObject(obj);
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private void writeNodes(Graph graph) throws IOException {
+        Map<Object, Object> props = new HashMap<>();
+        writeInt(graph.getNodeCount());
+        for (Node node : graph.getNodes()) {
+            NodeClass nodeClass = node.getNodeClass();
+            node.getDebugProperties(props);
+            writeInt(node.getId());
+            writePoolObject(nodeClass);
+            writeByte(node.predecessor() == null ? 0 : 1);
+            writeShort((char) props.size());
+            for (Entry<Object, Object> entry : props.entrySet()) {
+                String key = entry.getKey().toString();
+                writePoolObject(key);
+                writePropertyObject(entry.getValue());
+            }
+            // successors
+            NodeSuccessorsIterable successors = node.successors();
+            writeShort((char) successors.count());
+            NodeClassIterator suxIt = successors.iterator();
+            while (suxIt.hasNext()) {
+                Position pos = suxIt.nextPosition();
+                Node sux = nodeClass.get(node, pos);
+                writeInt(sux.getId());
+                writeShort((char) pos.index);
+            }
+            //inputs
+            NodeInputsIterable inputs = node.inputs();
+            writeShort((char) inputs.count());
+            NodeClassIterator inIt = inputs.iterator();
+            while (inIt.hasNext()) {
+                Position pos = inIt.nextPosition();
+                Node in = nodeClass.get(node, pos);
+                writeInt(in.getId());
+                writeShort((char) pos.index);
+            }
+            props.clear();
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private void writeBlocks(Block[] blocks, BlockMap<List<ScheduledNode>> blockToNodes) throws IOException {
+        if (blocks != null) {
+            writeInt(blocks.length);
+            for (Block block : blocks) {
+                List<ScheduledNode> nodes = blockToNodes.get(block);
+                writeInt(block.getId());
+                writeInt(nodes.size());
+                for (Node node : nodes) {
+                    writeInt(node.getId());
+                }
+                writeInt(block.getSuccessors().size());
+                for (Block sux : block.getSuccessors()) {
+                    writeInt(sux.getId());
+                }
+            }
+        } else {
+            writeInt(0);
+        }
+    }
+
+    public void beginGroup(String name, String shortName, ResolvedJavaMethod method, int bci) throws IOException {
+        writeByte(BEGIN_GROUP);
+        writePoolObject(name);
+        writePoolObject(shortName);
+        writePoolObject(method);
+        writeInt(bci);
+    }
+
+    public void endGroup() throws IOException {
+        writeByte(CLOSE_GROUP);
+    }
+
+    @Override
+    public void close() throws IOException {
+        flush();
+        channel.close();
+    }
+}
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Wed Jul 18 10:50:57 2012 -0700
@@ -192,4 +192,11 @@
         }
         return false;
     }
+
+    @Override
+    public void close() throws IOException {
+        if (cfgPrinter != null) {
+            cfgPrinter.close();
+        }
+    }
 }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Wed Jul 18 10:50:57 2012 -0700
@@ -36,7 +36,7 @@
  * The output format is such that it can then be fed to the
  * <a href="https://c1visualizer.dev.java.net/">C1 Visualizer</a>.
  */
-public class CompilationPrinter {
+public class CompilationPrinter implements Closeable {
     public static final String COLUMN_END = " <|@";
     public static final String HOVER_START = "<@";
     public static final String HOVER_SEP = "|@";
@@ -81,6 +81,11 @@
         out.flush();
     }
 
+    @Override
+    public void close() throws IOException {
+        out.out().close();
+    }
+
     protected void begin(String string) {
         out.println("begin_" + string);
         out.adjustIndentation(2);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinter.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,46 @@
+/*
+ * 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.printer;
+
+import java.io.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.schedule.*;
+import com.oracle.graal.graph.*;
+
+interface GraphPrinter extends Closeable {
+    /**
+     * Starts a new group of graphs with the given name, short name and method byte code index (BCI) as properties.
+     */
+    void beginGroup(String name, String shortName, ResolvedJavaMethod method, int bci) throws IOException;
+
+    /**
+     * Prints an entire {@link Graph} with the specified title, optionally using short names for nodes.
+     */
+    void print(Graph graph, String title, SchedulePhase predefinedSchedule) throws IOException;
+
+    /**
+     * Ends the current group.
+     */
+    void endGroup() throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,210 @@
+/*
+ * 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.printer;
+
+import java.io.*;
+import java.net.*;
+import java.nio.channels.*;
+import java.nio.file.*;
+import java.text.*;
+import java.util.*;
+
+import com.oracle.max.criutils.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+
+/**
+ * Observes compilation events and uses {@link IdealGraphPrinter} to generate a graph representation that can be
+ * inspected with the <a href="http://kenai.com/projects/igv">Ideal Graph Visualizer</a>.
+ */
+public class GraphPrinterDumpHandler implements DebugDumpHandler {
+    private static final SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd-HHmm");
+
+    private GraphPrinter printer;
+    private List<String> previousInlineContext;
+    private int failuresCount;
+
+    /**
+     * Creates a new {@link GraphPrinterDumpHandler}.
+     */
+    public GraphPrinterDumpHandler() {
+        previousInlineContext = new ArrayList<>();
+    }
+
+    private void ensureInitialized() {
+        if (printer == null) {
+            if (failuresCount > 8) {
+                return;
+            }
+            previousInlineContext.clear();
+            if (GraalOptions.PrintIdealGraphFile) {
+                initializeFilePrinter();
+            } else {
+                initializeNetworkPrinter();
+            }
+        }
+    }
+
+    private void initializeFilePrinter() {
+        String ext;
+        if (GraalOptions.PrintBinaryGraphs) {
+            ext = ".bgv";
+        } else {
+            ext = ".gv.xml";
+        }
+        String fileName = "Graphs-" + Thread.currentThread().getName() + "-" + sdf.format(new Date()) + ext;
+        try {
+            if (GraalOptions.PrintBinaryGraphs) {
+                printer = new BinaryGraphPrinter(FileChannel.open(new File(fileName).toPath(), StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW));
+            } else {
+                printer = new IdealGraphPrinter(new FileOutputStream(fileName));
+            }
+            TTY.println("Dumping IGV graphs to %s", fileName);
+        } catch (IOException e) {
+            TTY.println("Faild to open %s to dump IGV graphs : %s", fileName, e);
+            failuresCount++;
+            printer = null;
+        }
+    }
+
+    private void initializeNetworkPrinter() {
+        String host = GraalOptions.PrintIdealGraphAddress;
+        int port = GraalOptions.PrintBinaryGraphs ? GraalOptions.PrintBinaryGraphPort : GraalOptions.PrintIdealGraphPort;
+        try {
+            if (GraalOptions.PrintBinaryGraphs) {
+                printer = new BinaryGraphPrinter(SocketChannel.open(new InetSocketAddress(host, port)));
+            } else {
+                IdealGraphPrinter xmlPrinter = new IdealGraphPrinter(new Socket(host, port).getOutputStream());
+                printer = xmlPrinter;
+            }
+            TTY.println("Connected to the IGV on %s:%d", host, port);
+        } catch (IOException e) {
+            TTY.println("Could not connect to the IGV on %s:%d : %s", host, port, e);
+            failuresCount++;
+            printer = null;
+        }
+    }
+
+    @Override
+    public void dump(Object object, final String message) {
+        if (object instanceof Graph) {
+            ensureInitialized();
+            if (printer == null) {
+                return;
+            }
+            final Graph graph = (Graph) object;
+
+            if (printer != null) {
+                // Get all current RiResolvedMethod instances in the context.
+                List<String> inlineContext = getInlineContext();
+
+                // Reverse list such that inner method comes after outer method.
+                Collections.reverse(inlineContext);
+
+                // Check for method scopes that must be closed since the previous dump.
+                for (int i = 0; i < previousInlineContext.size(); ++i) {
+                    if (i >= inlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) {
+                        for (int j = previousInlineContext.size() - 1; j >= i; --j) {
+                            closeScope();
+                        }
+                        break;
+                    }
+                }
+
+                // Check for method scopes that must be opened since the previous dump.
+                for (int i = 0; i < inlineContext.size(); ++i) {
+                    if (i >= previousInlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) {
+                        for (int j = i; j < inlineContext.size(); ++j) {
+                            openScope(inlineContext.get(j), j == 0);
+                        }
+                        break;
+                    }
+                }
+
+                // Save inline context for next dump.
+                previousInlineContext = inlineContext;
+
+                Debug.sandbox("PrintingGraph", new Runnable() {
+
+                    @Override
+                    public void run() {
+                        // Finally, output the graph.
+                        try {
+                            printer.print(graph, message, null);
+                        } catch (IOException e) {
+                            failuresCount++;
+                            printer = null;
+                        }
+                    }
+                });
+            }
+        }
+    }
+
+    private static List<String> getInlineContext() {
+        List<String> result = new ArrayList<>();
+        for (Object o : Debug.context()) {
+            if (o instanceof ResolvedJavaMethod) {
+                ResolvedJavaMethod method = (ResolvedJavaMethod) o;
+                result.add(MetaUtil.format("%H::%n(%p)", method));
+            } else if (o instanceof DebugDumpScope) {
+                DebugDumpScope debugDumpScope = (DebugDumpScope) o;
+                if (debugDumpScope.decorator && !result.isEmpty()) {
+                    result.set(result.size() - 1, debugDumpScope.name + ":" + result.get(result.size() - 1));
+                } else {
+                    result.add(debugDumpScope.name);
+                }
+            }
+        }
+        return result;
+    }
+
+    private void openScope(String name, boolean showThread) {
+        String prefix = showThread ? Thread.currentThread().getName() + ":" : "";
+        try {
+            printer.beginGroup(prefix + name, name, Debug.contextLookup(ResolvedJavaMethod.class), -1);
+        } catch (IOException e) {
+            failuresCount++;
+            printer = null;
+        }
+    }
+
+    private void closeScope() {
+        try {
+            printer.endGroup();
+        } catch (IOException e) {
+            failuresCount++;
+            printer = null;
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        for (int i = 0; i < previousInlineContext.size(); i++) {
+            closeScope();
+        }
+        printer.close();
+    }
+}
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Wed Jul 18 10:50:57 2012 -0700
@@ -40,17 +40,19 @@
  * Generates a representation of {@link Graph Graphs} that can be visualized and inspected with the <a
  * href="http://kenai.com/projects/igv">Ideal Graph Visualizer</a>.
  */
-class IdealGraphPrinter extends BasicIdealGraphPrinter {
+class IdealGraphPrinter extends BasicIdealGraphPrinter implements GraphPrinter {
     /**
      * Creates a new {@link IdealGraphPrinter} that writes to the specified output stream.
      */
     public IdealGraphPrinter(OutputStream stream) {
         super(stream);
+        this.begin();
     }
 
     /**
      * Starts a new group of graphs with the given name, short name and method byte code index (BCI) as properties.
      */
+    @Override
     public void beginGroup(String name, String shortName, ResolvedJavaMethod method, int bci) {
         beginGroup();
         beginProperties();
@@ -70,6 +72,7 @@
     /**
      * Prints an entire {@link Graph} with the specified title, optionally using short names for nodes.
      */
+    @Override
     public void print(Graph graph, String title, SchedulePhase predefinedSchedule) {
         beginGraph(title);
         Set<Node> noBlockNodes = new HashSet<>();
@@ -79,12 +82,12 @@
                 schedule = new SchedulePhase();
                 schedule.apply((StructuredGraph) graph);
             } catch (Throwable t) {
-                schedule = null;
             }
         }
+        ControlFlowGraph cfg =  schedule == null ? null : schedule.getCFG();
 
         beginNodes();
-        List<Edge> edges = printNodes(graph, schedule == null ? null : schedule.getCFG().getNodeToBlock(), noBlockNodes);
+        List<Edge> edges = printNodes(graph, cfg == null ? null : cfg.getNodeToBlock(), noBlockNodes);
         endNodes();
 
         beginEdges();
@@ -93,10 +96,10 @@
         }
         endEdges();
 
-        if (schedule != null) {
+        if (cfg != null && cfg.getBlocks() != null) {
             beginControlFlow();
-            for (Block block : schedule.getCFG().getBlocks()) {
-                printBlock(graph, block, schedule.getCFG().getNodeToBlock());
+            for (Block block : cfg.getBlocks()) {
+                printBlock(graph, block, cfg.getNodeToBlock());
             }
             printNoBlock(noBlockNodes);
             endControlFlow();
@@ -158,11 +161,38 @@
                     printProperty(bit, "true");
                 }
             }
+            if (node.getClass() == BeginNode.class) {
+                printProperty("shortName", "B");
+            } else if (node.getClass() == EndNode.class) {
+                printProperty("shortName", "E");
+            }
+            if (node.predecessor() != null) {
+                printProperty("hasPredecessor", "true");
+            }
 
             for (Entry<Object, Object> entry : props.entrySet()) {
                 String key = entry.getKey().toString();
-                String value = entry.getValue() == null ? "null" : entry.getValue().toString();
-                printProperty(key, value);
+                Object value = entry.getValue();
+                String valueString;
+                if (value == null) {
+                    valueString = "null";
+                } else {
+                    Class<?> type = value.getClass();
+                    if (type.isArray()) {
+                        if (!type.getComponentType().isPrimitive()) {
+                            valueString = Arrays.toString((Object[]) value);
+                        } else if (type.getComponentType() == Integer.TYPE) {
+                            valueString = Arrays.toString((int[]) value);
+                        } else if (type.getComponentType() == Double.TYPE) {
+                            valueString = Arrays.toString((double[]) value);
+                        } else {
+                            valueString = toString();
+                        }
+                    } else {
+                        valueString = value.toString();
+                    }
+                }
+                printProperty(key, valueString);
             }
 
             endProperties();
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinterDumpHandler.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-/*
- * 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.printer;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-
-import com.oracle.max.criutils.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-
-/**
- * Observes compilation events and uses {@link IdealGraphPrinter} to generate a graph representation that can be
- * inspected with the <a href="http://kenai.com/projects/igv">Ideal Graph Visualizer</a>.
- */
-public class IdealGraphPrinterDumpHandler implements DebugDumpHandler {
-
-    private static final String DEFAULT_FILE_NAME = "output.igv.xml";
-
-    private IdealGraphPrinter printer;
-    private List<String> previousInlineContext = new ArrayList<>();
-    private String fileName;
-    private String host;
-    private int port;
-    private boolean initialized;
-
-    /**
-     * Creates a new {@link IdealGraphPrinterDumpHandler} that writes output to a file named after the compiled method.
-     */
-    public IdealGraphPrinterDumpHandler() {
-        this.fileName = DEFAULT_FILE_NAME;
-    }
-
-    /**
-     * Creates a new {@link IdealGraphPrinterDumpHandler} that sends output to a remote IdealGraphVisualizer instance.
-     */
-    public IdealGraphPrinterDumpHandler(String host, int port) {
-        this.host = host;
-        this.port = port;
-    }
-
-    private void ensureInitialized() {
-        if (!initialized) {
-            initialized = true;
-            if (fileName != null) {
-                initializeFilePrinter();
-            } else {
-                initializeNetworkPrinter();
-            }
-        }
-    }
-
-    private void initializeFilePrinter() {
-        try {
-            FileOutputStream stream = new FileOutputStream(fileName);
-            printer = new IdealGraphPrinter(stream);
-            printer.begin();
-        } catch (IOException e) {
-            printer = null;
-        }
-    }
-
-    private void initializeNetworkPrinter() {
-        try {
-            Socket socket = new Socket(host, port);
-            BufferedOutputStream stream = new BufferedOutputStream(socket.getOutputStream(), 0x4000);
-            printer = new IdealGraphPrinter(stream);
-            printer.begin();
-            TTY.println("Connected to the IGV on port %d", port);
-        } catch (IOException e) {
-            TTY.println("Could not connect to the IGV on port %d: %s", port, e);
-            printer = null;
-        }
-    }
-
-    @Override
-    public void dump(Object object, final String message) {
-        if (object instanceof Graph) {
-            ensureInitialized();
-            final Graph graph = (Graph) object;
-
-            if (printer != null && printer.isValid()) {
-                // Get all current RiResolvedMethod instances in the context.
-                List<String> inlineContext = getInlineContext();
-
-                // Reverse list such that inner method comes after outer method.
-                Collections.reverse(inlineContext);
-
-                // Check for method scopes that must be closed since the previous dump.
-                for (int i = 0; i < previousInlineContext.size(); ++i) {
-                    if (i >= inlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) {
-                        for (int j = previousInlineContext.size() - 1; j >= i; --j) {
-                            closeScope();
-                        }
-                        break;
-                    }
-                }
-
-                // Check for method scopes that must be opened since the previous dump.
-                for (int i = 0; i < inlineContext.size(); ++i) {
-                    if (i >= previousInlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) {
-                        for (int j = i; j < inlineContext.size(); ++j) {
-                            openScope(inlineContext.get(j), j == 0);
-                        }
-                        break;
-                    }
-                }
-
-                // Save inline context for next dump.
-                previousInlineContext = inlineContext;
-
-                Debug.sandbox("PrintingGraph", new Runnable() {
-
-                    @Override
-                    public void run() {
-                        // Finally, output the graph.
-                        printer.print(graph, message);
-
-                    }
-                });
-            }
-        }
-    }
-
-    private static List<String> getInlineContext() {
-        List<String> result = new ArrayList<>();
-        for (Object o : Debug.context()) {
-            if (o instanceof ResolvedJavaMethod) {
-                ResolvedJavaMethod method = (ResolvedJavaMethod) o;
-                result.add(MetaUtil.format("%H::%n(%p)", method));
-            } else if (o instanceof DebugDumpScope) {
-                DebugDumpScope debugDumpScope = (DebugDumpScope) o;
-                if (debugDumpScope.decorator && !result.isEmpty()) {
-                    result.set(result.size() - 1, debugDumpScope.name + ":" + result.get(result.size() - 1));
-                } else {
-                    result.add(debugDumpScope.name);
-                }
-            }
-        }
-        return result;
-    }
-
-    private void openScope(String name, boolean showThread) {
-        String prefix = showThread ? Thread.currentThread().getName() + ":" : "";
-        printer.beginGroup(prefix + name, name, Debug.contextLookup(ResolvedJavaMethod.class), -1);
-    }
-
-    private void closeScope() {
-        printer.endGroup();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/CheckCastTest.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,192 @@
+/*
+ * 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.snippets;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * Tests the implementation of checkcast, allowing profiling information to
+ * be manually specified.
+ */
+public class CheckCastTest extends TypeCheckTest {
+
+    /**
+     * Enables making the target type "unknown" at compile time.
+     */
+    boolean unknown;
+
+    @Override
+    protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
+        CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first();
+        if (ccn != null) {
+            ResolvedJavaType targetClass = unknown ? null : ccn.targetClass();
+            CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.targetClassInstruction(), targetClass, ccn.object(), profile));
+            graph.replaceFixedWithFixed(ccn, ccnNew);
+        }
+        unknown = false;
+    }
+
+    @Override
+    protected void test(String name, JavaTypeProfile profile, Object... args) {
+        super.test(name, profile, args);
+        unknown = true;
+        super.test(name, profile, args);
+    }
+
+    @Test
+    public void test1() {
+        test("asNumber",    profile(),                        111);
+        test("asNumber",    profile(Integer.class),           111);
+        test("asNumber",    profile(Long.class, Short.class), 111);
+        test("asNumberExt", profile(),                        111);
+        test("asNumberExt", profile(Integer.class),           111);
+        test("asNumberExt", profile(Long.class, Short.class), 111);
+    }
+
+    @Test
+    public void test2() {
+        test("asString",    profile(),             "111");
+        test("asString",    profile(String.class), "111");
+        test("asString",    profile(String.class), "111");
+
+        final String nullString = null;
+        test("asString",    profile(),             nullString);
+        test("asString",    profile(String.class), nullString);
+        test("asString",    profile(String.class), nullString);
+
+        test("asStringExt", profile(),             "111");
+        test("asStringExt", profile(String.class), "111");
+        test("asStringExt", profile(String.class), "111");
+    }
+
+    @Test
+    public void test3() {
+        test("asNumber", profile(), "111");
+    }
+
+    @Test
+    public void test4() {
+        test("asString", profile(String.class), 111);
+    }
+
+    @Test
+    public void test5() {
+        test("asNumberExt", profile(), "111");
+    }
+
+    @Test
+    public void test6() {
+        test("asStringExt", profile(String.class), 111);
+    }
+
+    @Test
+    public void test7() {
+        Throwable throwable = new Exception();
+        test("asThrowable",   profile(),                             throwable);
+        test("asThrowable",   profile(Throwable.class),              throwable);
+        test("asThrowable",   profile(Exception.class, Error.class), throwable);
+    }
+
+    @Test
+    public void test8() {
+        test("arrayFill", profile(), new Object[100], "111");
+    }
+
+    public static Number asNumber(Object o) {
+        return (Number) o;
+    }
+
+    public static String asString(Object o) {
+        return (String) o;
+    }
+
+    public static Throwable asThrowable(Object o) {
+        return (Throwable) o;
+    }
+
+    public static ValueNode asValueNode(Object o) {
+        return (ValueNode) o;
+    }
+
+    public static Number asNumberExt(Object o) {
+        Number n = (Number) o;
+        return n.intValue() + 10;
+    }
+
+    public static String asStringExt(Object o) {
+        String s = (String) o;
+        return "#" + s;
+    }
+
+    public static Object[] arrayFill(Object[] arr, Object value) {
+        for (int i = 0; i < arr.length; i++) {
+            arr[i] = value;
+        }
+        return arr;
+    }
+
+    static class Depth1 implements Cloneable {}
+    static class Depth2 extends Depth1 {}
+    static class Depth3 extends Depth2 {}
+    static class Depth4 extends Depth3 {}
+    static class Depth5 extends Depth4 {}
+    static class Depth6 extends Depth5 {}
+    static class Depth7 extends Depth6 {}
+    static class Depth8 extends Depth7 {}
+    static class Depth9 extends Depth8 {}
+    static class Depth10 extends Depth9 {}
+    static class Depth11 extends Depth10 {}
+    static class Depth12 extends Depth11 {}
+    static class Depth13 extends Depth12 {}
+    static class Depth14 extends Depth12 {}
+
+    public static Depth12 asDepth12(Object o) {
+        return (Depth12) o;
+    }
+
+    public static Depth12[][] asDepth12Arr(Object o) {
+        return (Depth12[][]) o;
+    }
+
+    public static Cloneable asCloneable(Object o) {
+        return (Cloneable) o;
+    }
+
+    @Test
+    public void test9() {
+        Object o = new Depth13();
+        test("asDepth12",   profile(), o);
+        test("asDepth12",   profile(Depth13.class), o);
+        test("asDepth12",   profile(Depth13.class, Depth14.class), o);
+    }
+
+    @Test
+    public void test10() {
+        Object o = new Depth13[3][];
+        test("asDepth12Arr",   profile(), o);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfTest.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,146 @@
+/*
+ * 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.snippets;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * Tests the implementation of instanceof, allowing profiling information to
+ * be manually specified.
+ */
+public class InstanceOfTest extends TypeCheckTest {
+
+    @Override
+    protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
+        InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first();
+        if (ion != null) {
+            InstanceOfNode ionNew = graph.add(new InstanceOfNode(ion.targetClassInstruction(), ion.targetClass(), ion.object(), profile));
+            graph.replaceFloating(ion, ionNew);
+        }
+    }
+
+    @Test
+    public void test1() {
+        test("isString",    profile(),                        "object");
+        test("isString",    profile(String.class),            "object");
+
+        test("isString",    profile(),                        Object.class);
+        test("isString",    profile(String.class),            Object.class);
+    }
+
+    @Test
+    public void test2() {
+        test("isStringInt",    profile(),                        "object");
+        test("isStringInt",    profile(String.class),            "object");
+
+        test("isStringInt",    profile(),                        Object.class);
+        test("isStringInt",    profile(String.class),            Object.class);
+    }
+
+    @Test
+    public void test3() {
+        Throwable throwable = new Exception();
+        test("isThrowable",    profile(),                             throwable);
+        test("isThrowable",    profile(Throwable.class),              throwable);
+        test("isThrowable",    profile(Exception.class, Error.class), throwable);
+
+        test("isThrowable",    profile(),                             Object.class);
+        test("isThrowable",    profile(Throwable.class),              Object.class);
+        test("isThrowable",    profile(Exception.class, Error.class), Object.class);
+    }
+
+    @Test
+    public void test4() {
+        Throwable throwable = new Exception();
+        test("isThrowableInt",    profile(),                             throwable);
+        test("isThrowableInt",    profile(Throwable.class),              throwable);
+        test("isThrowableInt",    profile(Exception.class, Error.class), throwable);
+
+        test("isThrowableInt",    profile(),                             Object.class);
+        test("isThrowableInt",    profile(Throwable.class),              Object.class);
+        test("isThrowableInt",    profile(Exception.class, Error.class), Object.class);
+    }
+
+    @Test
+    public void test5() {
+        Map map = new HashMap<>();
+        test("isMap",    profile(),                             map);
+        test("isMap",    profile(HashMap.class),                map);
+        test("isMap",    profile(TreeMap.class, HashMap.class), map);
+
+        test("isMap",    profile(),                             Object.class);
+        test("isMap",    profile(HashMap.class),                Object.class);
+        test("isMap",    profile(TreeMap.class, HashMap.class), Object.class);
+    }
+
+    @Test
+    public void test6() {
+        Map map = new HashMap<>();
+        test("isMapInt",    profile(),                             map);
+        test("isMapInt",    profile(HashMap.class),                map);
+        test("isMapInt",    profile(TreeMap.class, HashMap.class), map);
+
+        test("isMapInt",    profile(),                             Object.class);
+        test("isMapInt",    profile(HashMap.class),                Object.class);
+        test("isMapInt",    profile(TreeMap.class, HashMap.class), Object.class);
+    }
+
+    public static boolean isString(Object o) {
+        return o instanceof String;
+    }
+
+    public static int isStringInt(Object o) {
+        if (o instanceof String) {
+            return 1;
+        }
+        return 0;
+    }
+
+    public static boolean isThrowable(Object o) {
+        return o instanceof Throwable;
+    }
+
+    public static int isThrowableInt(Object o) {
+        if (o instanceof Throwable) {
+            return 1;
+        }
+        return 0;
+    }
+
+    public static boolean isMap(Object o) {
+        return o instanceof Map;
+    }
+
+    public static int isMapInt(Object o) {
+        if (o instanceof Map) {
+            return 1;
+        }
+        return 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InvokeTest.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,103 @@
+/*
+ * 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.snippets;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.phases.*;
+import com.oracle.graal.compiler.tests.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Tests the implementation of the snippets for lowering the INVOKE* instructions.
+ */
+public class InvokeTest extends GraalCompilerTest {
+
+    @Override
+    protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) {
+        phasePlan.disablePhase(InliningPhase.class);
+    }
+
+    public interface I {
+        String virtualMethod(String s);
+    }
+
+    public static class A implements I {
+        final String name = "A";
+        public String virtualMethod(String s) {
+            return name + s;
+        }
+    }
+
+    @SuppressWarnings("static-method")
+    private String privateMethod(String s) {
+        return s;
+    }
+
+    @Test
+    public void test1() {
+        test("invokestatic", "a string");
+        test("invokespecialConstructor", "a string");
+        test("invokespecial", this, "a string");
+        test("invokevirtual", new A(), "a string");
+        test("invokevirtual2", new A(), "a string");
+        test("invokeinterface", new A(), "a string");
+        Object[] args = {null};
+        test("invokestatic", args);
+        test("invokespecialConstructor", args);
+        test("invokespecial", null, null);
+        test("invokevirtual", null, null);
+        test("invokevirtual2", null, null);
+        test("invokeinterface", null, null);
+    }
+
+    public static String invokestatic(String s) {
+        return staticMethod(s);
+    }
+
+    public static String staticMethod(String s) {
+        return s;
+    }
+
+    public static String invokespecialConstructor(String s) {
+        return new A().virtualMethod(s);
+    }
+
+    public static String invokespecial(InvokeTest a, String s) {
+        return a.privateMethod(s);
+    }
+
+    public static String invokevirtual(A a, String s) {
+        return a.virtualMethod(s);
+    }
+
+    public static String invokevirtual2(A a, String s) {
+        a.virtualMethod(s);
+        return a.virtualMethod(s);
+    }
+
+    public static String invokeinterface(I i, String s) {
+        return i.virtualMethod(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/NewArrayTest.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,167 @@
+/*
+ * 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.snippets;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.tests.*;
+
+/**
+ * Tests the implementation of {@code [A]NEWARRAY}.
+ */
+public class NewArrayTest extends GraalCompilerTest {
+
+    @Override
+    protected void assertEquals(Object expected, Object actual) {
+        Assert.assertTrue(expected != null);
+        Assert.assertTrue(actual != null);
+        super.assertEquals(expected.getClass(), actual.getClass());
+        if (expected instanceof int[]) {
+            Assert.assertArrayEquals((int[]) expected, (int[]) actual);
+        } else if (expected instanceof byte[]) {
+            Assert.assertArrayEquals((byte[]) expected, (byte[]) actual);
+        } else if (expected instanceof char[]) {
+            Assert.assertArrayEquals((char[]) expected, (char[]) actual);
+        } else if (expected instanceof short[]) {
+            Assert.assertArrayEquals((short[]) expected, (short[]) actual);
+        } else if (expected instanceof float[]) {
+            Assert.assertArrayEquals((float[]) expected, (float[]) actual, 0.0f);
+        } else if (expected instanceof long[]) {
+            Assert.assertArrayEquals((long[]) expected, (long[]) actual);
+        } else if (expected instanceof double[]) {
+            Assert.assertArrayEquals((double[]) expected, (double[]) actual, 0.0d);
+        } else if (expected instanceof Object[]) {
+            Assert.assertArrayEquals((Object[]) expected, (Object[]) actual);
+        } else {
+            Assert.fail("non-array value encountered: " + expected);
+        }
+    }
+
+    @Test
+    public void test1() {
+        for (String type : new String[] {"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) {
+            test("new" + type + "Array7");
+            test("new" + type + "ArrayMinus7");
+            test("new" + type + "Array", 7);
+            test("new" + type + "Array", -7);
+            test("new" + type + "Array", Integer.MAX_VALUE);
+            test("new" + type + "Array", Integer.MIN_VALUE);
+        }
+    }
+
+    public static Object newCharArray7() {
+        return new char[7];
+    }
+
+    public static Object newCharArrayMinus7() {
+        return new char[-7];
+    }
+
+    public static Object newCharArray(int length) {
+        return new char[length];
+    }
+
+    public static Object newShortArray7() {
+        return new short[7];
+    }
+
+    public static Object newShortArrayMinus7() {
+        return new short[-7];
+    }
+
+    public static Object newShortArray(int length) {
+        return new short[length];
+    }
+
+    public static Object newFloatArray7() {
+        return new float[7];
+    }
+
+    public static Object newFloatArrayMinus7() {
+        return new float[-7];
+    }
+
+    public static Object newFloatArray(int length) {
+        return new float[length];
+    }
+
+    public static Object newLongArray7() {
+        return new long[7];
+    }
+
+    public static Object newLongArrayMinus7() {
+        return new long[-7];
+    }
+
+    public static Object newLongArray(int length) {
+        return new long[length];
+    }
+
+    public static Object newDoubleArray7() {
+        return new double[7];
+    }
+
+    public static Object newDoubleArrayMinus7() {
+        return new double[-7];
+    }
+
+    public static Object newDoubleArray(int length) {
+        return new double[length];
+    }
+
+    public static Object newIntArray7() {
+        return new int[7];
+    }
+
+    public static Object newIntArrayMinus7() {
+        return new int[-7];
+    }
+
+    public static Object newIntArray(int length) {
+        return new int[length];
+    }
+
+    public static Object newByteArray7() {
+        return new byte[7];
+    }
+
+    public static Object newByteArrayMinus7() {
+        return new byte[-7];
+    }
+
+    public static Object newByteArray(int length) {
+        return new byte[length];
+    }
+
+    public static Object newStringArray7() {
+        return new String[7];
+    }
+
+    public static Object newStringArrayMinus7() {
+        return new String[-7];
+    }
+
+    public static Object newStringArray(int length) {
+        return new String[length];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/NewInstanceTest.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,190 @@
+/*
+ * 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.snippets;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.tests.*;
+
+/**
+ * Tests the implementation of {@code NEW}.
+ */
+public class NewInstanceTest extends GraalCompilerTest {
+
+    @Override
+    protected void assertEquals(Object expected, Object actual) {
+        Assert.assertTrue(expected != null);
+        Assert.assertTrue(actual != null);
+        super.assertEquals(expected.getClass(), actual.getClass());
+        if (expected.getClass() != Object.class) {
+            try {
+                expected.getClass().getDeclaredMethod("equals", Object.class);
+                super.assertEquals(expected, actual);
+            } catch (Exception e) {
+            }
+        }
+    }
+
+    @Test
+    public void test1() {
+        test("newObject");
+        test("newBigObject");
+        test("newSomeObject");
+        test("newEmptyString");
+        test("newString", "value");
+        test("newHashMap", 31);
+        test("newRegression", true);
+    }
+
+    public static Object newObject() {
+        return new Object();
+    }
+
+    public static BigObject newBigObject() {
+        return new BigObject();
+    }
+
+    public static SomeObject newSomeObject() {
+        return new SomeObject();
+    }
+
+    public static String newEmptyString() {
+        return new String();
+    }
+
+    public static String newString(String value) {
+        return new String(value);
+    }
+
+    public static HashMap newHashMap(int initialCapacity) {
+        return new HashMap(initialCapacity);
+    }
+
+    static class SomeObject {
+        String name = "o1";
+        HashMap<String, Object> map = new HashMap<>();
+
+
+        public SomeObject() {
+            map.put(name, this.getClass());
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof SomeObject) {
+                SomeObject so = (SomeObject) obj;
+                return so.name.equals(name) && so.map.equals(map);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
+    }
+
+    static class BigObject {
+        Object f01;
+        Object f02;
+        Object f03;
+        Object f04;
+        Object f05;
+        Object f06;
+        Object f07;
+        Object f08;
+        Object f09;
+        Object f10;
+        Object f12;
+        Object f13;
+        Object f14;
+        Object f15;
+        Object f16;
+        Object f17;
+        Object f18;
+        Object f19;
+        Object f20;
+        Object f21;
+        Object f22;
+        Object f23;
+        Object f24;
+        Object f25;
+        Object f26;
+        Object f27;
+        Object f28;
+        Object f29;
+        Object f30;
+        Object f31;
+        Object f32;
+        Object f33;
+        Object f34;
+        Object f35;
+        Object f36;
+        Object f37;
+        Object f38;
+        Object f39;
+        Object f40;
+        Object f41;
+        Object f42;
+        Object f43;
+        Object f44;
+        Object f45;
+    }
+
+    /**
+     * Tests that an earlier bug does not occur. The issue was that the loading of the TLAB
+     * 'top' and 'end' values was being GVN'ed from each branch of the 'if' statement.
+     * This meant that the allocated B object in the true branch overwrote the allocated
+     * array. The cause is that RegisterNode was a floating node and the reads from it
+     * were UnsafeLoads which are also floating. The fix was to make RegisterNode a fixed
+     * node (which it should have been in the first place).
+     */
+    public static Object newRegression(boolean condition) {
+        Object result;
+        if (condition) {
+            Object[] arr = {0, 1, 2, 3, 4, 5};
+            result = new B();
+            for (int i = 0; i < arr.length; ++i) {
+                // If the bug exists, the values of arr will now be deadbeef values
+                // and the virtual dispatch will cause a segfault. This can result in
+                // either a VM crash or a spurious NullPointerException.
+                if (arr[i].equals(Integer.valueOf(i))) {
+                    return false;
+                }
+            }
+        } else {
+            result = new B();
+        }
+        return result;
+    }
+
+    static class B {
+        long f1 = 0xdeadbeefdeadbe01L;
+        long f2 = 0xdeadbeefdeadbe02L;
+        long f3 = 0xdeadbeefdeadbe03L;
+        long f4 = 0xdeadbeefdeadbe04L;
+        long f5 = 0xdeadbeefdeadbe05L;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/TypeCheckTest.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,70 @@
+/*
+ * 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.snippets;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
+import com.oracle.graal.compiler.tests.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Base class for checkcast and instanceof test classes.
+ */
+public abstract class TypeCheckTest extends GraalCompilerTest {
+
+    protected abstract void replaceProfile(StructuredGraph graph, JavaTypeProfile profile);
+
+    protected JavaTypeProfile currentProfile;
+
+    @Override
+    protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) {
+        boolean forceCompile = false;
+        if (currentProfile != null) {
+            replaceProfile(graph, currentProfile);
+            forceCompile = true;
+        }
+        return super.getCode(method, graph, forceCompile);
+    }
+
+    protected JavaTypeProfile profile(Class... types) {
+        if (types.length == 0) {
+            return null;
+        }
+        ProfiledType[] ptypes = new ProfiledType[types.length];
+        for (int i = 0; i < types.length; i++) {
+            ptypes[i] = new ProfiledType(runtime.getResolvedJavaType(types[i]), 1.0D / types.length);
+        }
+        return new JavaTypeProfile(0.0D, ptypes);
+    }
+
+    protected void test(String name, JavaTypeProfile profile, Object... args) {
+        assert currentProfile == null;
+        currentProfile = profile;
+        try {
+            super.test(name, args);
+        } finally {
+            currentProfile = null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetCounter.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,154 @@
+/*
+ * 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.snippets;
+
+//JaCoCo Exclude
+
+import java.io.*;
+import java.util.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.snippets.Snippet.Fold;
+import com.oracle.graal.snippets.nodes.*;
+
+/**
+ * A counter that can be safely {@linkplain #inc() incremented} from within a
+ * snippet for gathering snippet specific metrics.
+ */
+public class SnippetCounter implements Comparable<SnippetCounter> {
+
+    /**
+     * A group of related counters.
+     */
+    public static class Group {
+        final String name;
+        final List<SnippetCounter> counters;
+
+        public Group(String name) {
+            this.name = name;
+            this.counters = new ArrayList<>();
+        }
+
+        @Override
+        public synchronized String toString() {
+            Collections.sort(counters);
+
+            long total = 0;
+            int maxNameLen = 0;
+            for (SnippetCounter c : counters) {
+                total += c.value;
+                maxNameLen = Math.max(c.name.length(), maxNameLen);
+            }
+
+            StringBuilder buf = new StringBuilder(String.format("Counters: %s%n", name));
+
+            for (SnippetCounter c : counters) {
+                double percent = total == 0D ? 0D : ((double) (c.value * 100)) / total;
+                buf.append(String.format("  %" + maxNameLen + "s: %5.2f%%%10d  // %s%n", c.name, percent, c.value, c.description));
+            }
+            return buf.toString();
+        }
+    }
+
+    /**
+     * Sorts counters in descending order of their {@linkplain #value() values}.
+     */
+    @Override
+    public int compareTo(SnippetCounter o) {
+        if (value > o.value) {
+            return -1;
+        } else if (o.value < value) {
+            return 1;
+        }
+        return 0;
+    }
+
+    private static final List<Group> groups = new ArrayList<>();
+
+    private final Group group;
+    private final int index;
+    private final String name;
+    private final String description;
+    private long value;
+
+    @Fold
+    private static int countOffset() {
+        try {
+            return (int) Unsafe.getUnsafe().objectFieldOffset(SnippetCounter.class.getDeclaredField("value"));
+        } catch (Exception e) {
+            throw new GraalInternalError(e);
+        }
+    }
+
+    /**
+     * Creates a counter.
+     *
+     * @param group the group to which the counter belongs. If this is null, the newly created counter is disabled and
+     *            {@linkplain #inc() incrementing} is a no-op.
+     * @param name the name of the counter
+     * @param description a brief comment describing the metric represented by the counter
+     */
+    public SnippetCounter(Group group, String name, String description) {
+        this.group = group;
+        this.name = name;
+        this.description = description;
+        if (group != null) {
+            List<SnippetCounter> counters = group.counters;
+            this.index = counters.size();
+            counters.add(this);
+            if (index == 0) {
+                groups.add(group);
+            }
+        } else {
+            this.index = -1;
+        }
+    }
+
+    /**
+     * Increments the value of this counter. This method can be safely used in a snippet
+     * if it is invoked on a compile-time constant {@link SnippetCounter} object.
+     */
+    public void inc() {
+        if (group != null) {
+            DirectObjectStoreNode.storeLong(this, countOffset(), 0, value + 1);
+        }
+    }
+
+    /**
+     * Gets the value of this counter.
+     */
+    public long value() {
+        return value;
+    }
+
+    /**
+     * Prints all the counter groups to a given stream.
+     */
+    public static void printGroups(PrintStream out) {
+        for (Group group : groups) {
+            out.println(group);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectObjectStoreNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,80 @@
+/*
+ * 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.snippets.nodes;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.snippets.*;
+
+/**
+ * A special purpose store node that differs from {@link UnsafeStoreNode} in that
+ * it is not a {@link StateSplit} and does not include a write barrier.
+ */
+public class DirectObjectStoreNode extends FixedWithNextNode implements Lowerable {
+    @Input private ValueNode object;
+    @Input private ValueNode value;
+    @Input private ValueNode offset;
+    private final int displacement;
+
+    public DirectObjectStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value) {
+        super(StampFactory.forVoid());
+        this.object = object;
+        this.value = value;
+        this.offset = offset;
+        this.displacement = displacement;
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static void storeObject(Object obj, @ConstantNodeParameter int displacement, long offset, Object value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static void storeLong(Object obj, @ConstantNodeParameter int displacement, long offset, long value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static void storeWord(Object obj, @ConstantNodeParameter int displacement, long offset, Word value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static void storeInt(Object obj, @ConstantNodeParameter int displacement, long offset, int value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        StructuredGraph graph = (StructuredGraph) this.graph();
+        IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, false);
+        WriteNode write = graph.add(new WriteNode(object, value, location));
+        graph.replaceFixedWithFixed(this, write);
+    }
+}
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CheckCastTest.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-/*
- * 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.api.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-
-/**
- * Tests the implementation of checkcast, allowing profiling information to
- * be manually specified.
- */
-public class CheckCastTest extends TypeCheckTest {
-
-    /**
-     * Enables making the target type "unknown" at compile time.
-     */
-    boolean unknown;
-
-    @Override
-    protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
-        CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first();
-        if (ccn != null) {
-            ResolvedJavaType targetClass = unknown ? null : ccn.targetClass();
-            CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.targetClassInstruction(), targetClass, ccn.object(), profile));
-            graph.replaceFixedWithFixed(ccn, ccnNew);
-        }
-        unknown = false;
-    }
-
-    @Override
-    protected void test(String name, JavaTypeProfile profile, Object... args) {
-        super.test(name, profile, args);
-        unknown = true;
-        super.test(name, profile, args);
-    }
-
-    @Test
-    public void test1() {
-        test("asNumber",    profile(),                        111);
-        test("asNumber",    profile(Integer.class),           111);
-        test("asNumber",    profile(Long.class, Short.class), 111);
-        test("asNumberExt", profile(),                        111);
-        test("asNumberExt", profile(Integer.class),           111);
-        test("asNumberExt", profile(Long.class, Short.class), 111);
-    }
-
-    @Test
-    public void test2() {
-        test("asString",    profile(),             "111");
-        test("asString",    profile(String.class), "111");
-        test("asString",    profile(String.class), "111");
-
-        final String nullString = null;
-        test("asString",    profile(),             nullString);
-        test("asString",    profile(String.class), nullString);
-        test("asString",    profile(String.class), nullString);
-
-        test("asStringExt", profile(),             "111");
-        test("asStringExt", profile(String.class), "111");
-        test("asStringExt", profile(String.class), "111");
-    }
-
-    @Test
-    public void test3() {
-        test("asNumber", profile(), "111");
-    }
-
-    @Test
-    public void test4() {
-        test("asString", profile(String.class), 111);
-    }
-
-    @Test
-    public void test5() {
-        test("asNumberExt", profile(), "111");
-    }
-
-    @Test
-    public void test6() {
-        test("asStringExt", profile(String.class), 111);
-    }
-
-    @Test
-    public void test7() {
-        Throwable throwable = new Exception();
-        test("asThrowable",   profile(),                             throwable);
-        test("asThrowable",   profile(Throwable.class),              throwable);
-        test("asThrowable",   profile(Exception.class, Error.class), throwable);
-    }
-
-    @Test
-    public void test8() {
-        test("arrayFill", profile(), new Object[100], "111");
-    }
-
-    public static Number asNumber(Object o) {
-        return (Number) o;
-    }
-
-    public static String asString(Object o) {
-        return (String) o;
-    }
-
-    public static Throwable asThrowable(Object o) {
-        return (Throwable) o;
-    }
-
-    public static ValueNode asValueNode(Object o) {
-        return (ValueNode) o;
-    }
-
-    public static Number asNumberExt(Object o) {
-        Number n = (Number) o;
-        return n.intValue() + 10;
-    }
-
-    public static String asStringExt(Object o) {
-        String s = (String) o;
-        return "#" + s;
-    }
-
-    public static Object[] arrayFill(Object[] arr, Object value) {
-        for (int i = 0; i < arr.length; i++) {
-            arr[i] = value;
-        }
-        return arr;
-    }
-
-    static class Depth1 implements Cloneable {}
-    static class Depth2 extends Depth1 {}
-    static class Depth3 extends Depth2 {}
-    static class Depth4 extends Depth3 {}
-    static class Depth5 extends Depth4 {}
-    static class Depth6 extends Depth5 {}
-    static class Depth7 extends Depth6 {}
-    static class Depth8 extends Depth7 {}
-    static class Depth9 extends Depth8 {}
-    static class Depth10 extends Depth9 {}
-    static class Depth11 extends Depth10 {}
-    static class Depth12 extends Depth11 {}
-    static class Depth13 extends Depth12 {}
-    static class Depth14 extends Depth12 {}
-
-    public static Depth12 asDepth12(Object o) {
-        return (Depth12) o;
-    }
-
-    public static Depth12[][] asDepth12Arr(Object o) {
-        return (Depth12[][]) o;
-    }
-
-    public static Cloneable asCloneable(Object o) {
-        return (Cloneable) o;
-    }
-
-    @Test
-    public void test9() {
-        Object o = new Depth13();
-        test("asDepth12",   profile(), o);
-        test("asDepth12",   profile(Depth13.class), o);
-        test("asDepth12",   profile(Depth13.class, Depth14.class), o);
-    }
-
-    @Test
-    public void test10() {
-        Object o = new Depth13[3][];
-        test("asDepth12Arr",   profile(), o);
-    }
-}
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java	Wed Jul 18 10:50:57 2012 -0700
@@ -26,8 +26,9 @@
 
 import org.junit.*;
 
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.InstalledCode.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.InstalledCode.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraalCompilerTest.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraalCompilerTest.java	Wed Jul 18 10:50:57 2012 -0700
@@ -53,7 +53,7 @@
  * <li>Assert that the transformed graph is equal to an expected graph.</li>
  * </ol>
  * <p>
- * See {@link InvokeTest} as an example.
+ * See {@link InvokeHintsTest} as an example.
  * <p>
  * The tests can be run in Eclipse with the "Compiler Unit Test" Eclipse
  * launch configuration found in the top level of this project or by
@@ -62,10 +62,12 @@
 public abstract class GraalCompilerTest {
 
     protected final GraalCodeCacheProvider runtime;
+    protected final GraalCompiler graalCompiler;
 
     public GraalCompilerTest() {
         Debug.enable();
         this.runtime = Graal.getRuntime().getCapability(GraalCodeCacheProvider.class);
+        this.graalCompiler = Graal.getRuntime().getCapability(GraalCompiler.class);
     }
 
     protected void assertEquals(StructuredGraph expected, StructuredGraph graph) {
@@ -198,6 +200,16 @@
     }
 
     /**
+     * Can be overridden to modify the compilation phases applied for a test.
+     *
+     * @param method the method being compiled
+     * @param graph the graph being compiled
+     * @param phasePlan the phase plan to be edited
+     */
+    protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) {
+    }
+
+    /**
      * Gets installed code for a given method and graph, compiling it first if necessary.
      *
      * @param forceCompile specifies whether to ignore any previous code cached for the (method, key) pair
@@ -211,24 +223,27 @@
         }
         InstalledCode installedCode = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(compilationId++), true), new Callable<InstalledCode>() {
             public InstalledCode call() throws Exception {
-                CompilationResult targetMethod = runtime.compile(method, graph);
-                return addMethod(method, targetMethod);
+                PhasePlan phasePlan = new PhasePlan();
+                GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
+                phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+                editPhasePlan(method, graph, phasePlan);
+                CompilationResult compResult = graalCompiler.compileMethod(method, graph, -1, null, phasePlan, OptimisticOptimizations.ALL);
+                return addMethod(method, compResult);
             }
         });
         cache.put(method, installedCode);
         return installedCode;
     }
 
-    protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult tm) {
-        GraalCompiler graalCompiler = Graal.getRuntime().getCapability(GraalCompiler.class);
+    protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult) {
         assert graalCompiler != null;
         return Debug.scope("CodeInstall", new Object[] {graalCompiler, method}, new Callable<InstalledCode>() {
             @Override
             public InstalledCode call() throws Exception {
                 final CodeInfo[] info = Debug.isDumpEnabled() ? new CodeInfo[1] : null;
-                InstalledCode installedMethod = runtime.addMethod(method, tm, info);
+                InstalledCode installedMethod = runtime.addMethod(method, compResult, info);
                 if (info != null) {
-                    Debug.dump(new Object[] {tm, info[0]}, "After code installation");
+                    Debug.dump(new Object[] {compResult, info[0]}, "After code installation");
                 }
                 return installedMethod;
             }
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InstanceOfTest.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/*
- * 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 java.util.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-
-/**
- * Tests the implementation of instanceof, allowing profiling information to
- * be manually specified.
- */
-public class InstanceOfTest extends TypeCheckTest {
-
-    @Override
-    protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
-        InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first();
-        if (ion != null) {
-            InstanceOfNode ionNew = graph.add(new InstanceOfNode(ion.targetClassInstruction(), ion.targetClass(), ion.object(), profile));
-            graph.replaceFloating(ion, ionNew);
-        }
-    }
-
-    @Test
-    public void test1() {
-        test("isString",    profile(),                        "object");
-        test("isString",    profile(String.class),            "object");
-
-        test("isString",    profile(),                        Object.class);
-        test("isString",    profile(String.class),            Object.class);
-    }
-
-    @Test
-    public void test2() {
-        test("isStringInt",    profile(),                        "object");
-        test("isStringInt",    profile(String.class),            "object");
-
-        test("isStringInt",    profile(),                        Object.class);
-        test("isStringInt",    profile(String.class),            Object.class);
-    }
-
-    @Test
-    public void test3() {
-        Throwable throwable = new Exception();
-        test("isThrowable",    profile(),                             throwable);
-        test("isThrowable",    profile(Throwable.class),              throwable);
-        test("isThrowable",    profile(Exception.class, Error.class), throwable);
-
-        test("isThrowable",    profile(),                             Object.class);
-        test("isThrowable",    profile(Throwable.class),              Object.class);
-        test("isThrowable",    profile(Exception.class, Error.class), Object.class);
-    }
-
-    @Test
-    public void test4() {
-        Throwable throwable = new Exception();
-        test("isThrowableInt",    profile(),                             throwable);
-        test("isThrowableInt",    profile(Throwable.class),              throwable);
-        test("isThrowableInt",    profile(Exception.class, Error.class), throwable);
-
-        test("isThrowableInt",    profile(),                             Object.class);
-        test("isThrowableInt",    profile(Throwable.class),              Object.class);
-        test("isThrowableInt",    profile(Exception.class, Error.class), Object.class);
-    }
-
-    @Test
-    public void test5() {
-        Map map = new HashMap<>();
-        test("isMap",    profile(),                             map);
-        test("isMap",    profile(HashMap.class),                map);
-        test("isMap",    profile(TreeMap.class, HashMap.class), map);
-
-        test("isMap",    profile(),                             Object.class);
-        test("isMap",    profile(HashMap.class),                Object.class);
-        test("isMap",    profile(TreeMap.class, HashMap.class), Object.class);
-    }
-
-    @Test
-    public void test6() {
-        Map map = new HashMap<>();
-        test("isMapInt",    profile(),                             map);
-        test("isMapInt",    profile(HashMap.class),                map);
-        test("isMapInt",    profile(TreeMap.class, HashMap.class), map);
-
-        test("isMapInt",    profile(),                             Object.class);
-        test("isMapInt",    profile(HashMap.class),                Object.class);
-        test("isMapInt",    profile(TreeMap.class, HashMap.class), Object.class);
-    }
-
-    public static boolean isString(Object o) {
-        return o instanceof String;
-    }
-
-    public static int isStringInt(Object o) {
-        if (o instanceof String) {
-            return 1;
-        }
-        return 0;
-    }
-
-    public static boolean isThrowable(Object o) {
-        return o instanceof Throwable;
-    }
-
-    public static int isThrowableInt(Object o) {
-        if (o instanceof Throwable) {
-            return 1;
-        }
-        return 0;
-    }
-
-    public static boolean isMap(Object o) {
-        return o instanceof Map;
-    }
-
-    public static int isMapInt(Object o) {
-        if (o instanceof Map) {
-            return 1;
-        }
-        return 0;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeHintsTest.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,82 @@
+/*
+ * 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 java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.phases.*;
+import com.oracle.graal.nodes.*;
+
+public class InvokeHintsTest extends GraalCompilerTest {
+
+    private static final String REFERENCE_SNIPPET = "referenceSnippet";
+
+    public static int const1() {
+        return 1;
+    }
+
+    public static int const7() {
+        return 7;
+    }
+
+    @SuppressWarnings("all")
+    public static int referenceSnippet() {
+        return 7;
+    }
+
+    @Test
+    public void test1() {
+        test("test1Snippet");
+    }
+
+    @SuppressWarnings("all")
+    public static int test1Snippet() {
+        return const7();
+    }
+
+    @Test
+    public void test2() {
+        test("test2Snippet");
+    }
+
+    @SuppressWarnings("all")
+    public static int test2Snippet() {
+        return const1() + const1() + const1() + const1() + const1() + const1() + const1();
+    }
+
+    private void test(String snippet) {
+        StructuredGraph graph = parse(snippet);
+        Collection<Invoke> hints = new ArrayList<>();
+        for (Invoke invoke : graph.getInvokes()) {
+            hints.add(invoke);
+        }
+        new InliningPhase(null, runtime(), hints, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+        new CanonicalizerPhase(null, runtime(), null).apply(graph);
+        new DeadCodeEliminationPhase().apply(graph);
+        StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
+        assertEquals(referenceGraph, graph);
+    }
+}
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeTest.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * 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 java.util.*;
-
-import org.junit.*;
-
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.nodes.*;
-
-/**
- * In the following tests, the usages of local variable "a" are replaced with the integer constant 0.
- * Then canonicalization is applied and it is verified that the resulting graph is equal to the
- * graph of the method that just has a "return 1" statement in it.
- */
-public class InvokeTest extends GraalCompilerTest {
-
-    private static final String REFERENCE_SNIPPET = "referenceSnippet";
-
-    public static int const1() {
-        return 1;
-    }
-
-    public static int const7() {
-        return 7;
-    }
-
-    @SuppressWarnings("all")
-    public static int referenceSnippet() {
-        return 7;
-    }
-
-    @Test
-    public void test1() {
-        test("test1Snippet");
-    }
-
-    @SuppressWarnings("all")
-    public static int test1Snippet() {
-        return const7();
-    }
-
-    @Test
-    public void test2() {
-        test("test2Snippet");
-    }
-
-    @SuppressWarnings("all")
-    public static int test2Snippet() {
-        return const1() + const1() + const1() + const1() + const1() + const1() + const1();
-    }
-
-    private void test(String snippet) {
-        StructuredGraph graph = parse(snippet);
-        Collection<Invoke> hints = new ArrayList<>();
-        for (Invoke invoke : graph.getInvokes()) {
-            hints.add(invoke);
-        }
-        new InliningPhase(null, runtime(), hints, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
-        new CanonicalizerPhase(null, runtime(), null).apply(graph);
-        new DeadCodeEliminationPhase().apply(graph);
-        StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
-        assertEquals(referenceGraph, graph);
-    }
-}
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/NewArrayTest.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-/*
- * 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.*;
-
-/**
- * Tests the implementation of {@code [A]NEWARRAY}.
- */
-public class NewArrayTest extends GraalCompilerTest {
-
-    @Override
-    protected void assertEquals(Object expected, Object actual) {
-        Assert.assertTrue(expected != null);
-        Assert.assertTrue(actual != null);
-        super.assertEquals(expected.getClass(), actual.getClass());
-        if (expected instanceof int[]) {
-            Assert.assertArrayEquals((int[]) expected, (int[]) actual);
-        } else if (expected instanceof byte[]) {
-            Assert.assertArrayEquals((byte[]) expected, (byte[]) actual);
-        } else if (expected instanceof char[]) {
-            Assert.assertArrayEquals((char[]) expected, (char[]) actual);
-        } else if (expected instanceof short[]) {
-            Assert.assertArrayEquals((short[]) expected, (short[]) actual);
-        } else if (expected instanceof float[]) {
-            Assert.assertArrayEquals((float[]) expected, (float[]) actual, 0.0f);
-        } else if (expected instanceof long[]) {
-            Assert.assertArrayEquals((long[]) expected, (long[]) actual);
-        } else if (expected instanceof double[]) {
-            Assert.assertArrayEquals((double[]) expected, (double[]) actual, 0.0d);
-        } else if (expected instanceof Object[]) {
-            Assert.assertArrayEquals((Object[]) expected, (Object[]) actual);
-        } else {
-            Assert.fail("non-array value encountered: " + expected);
-        }
-    }
-
-    @Test
-    public void test1() {
-        for (String type : new String[] {"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) {
-            test("new" + type + "Array7");
-            test("new" + type + "ArrayMinus7");
-            test("new" + type + "Array", 7);
-            test("new" + type + "Array", -7);
-            test("new" + type + "Array", Integer.MAX_VALUE);
-            test("new" + type + "Array", Integer.MIN_VALUE);
-        }
-    }
-
-    public static Object newCharArray7() {
-        return new char[7];
-    }
-
-    public static Object newCharArrayMinus7() {
-        return new char[-7];
-    }
-
-    public static Object newCharArray(int length) {
-        return new char[length];
-    }
-
-    public static Object newShortArray7() {
-        return new short[7];
-    }
-
-    public static Object newShortArrayMinus7() {
-        return new short[-7];
-    }
-
-    public static Object newShortArray(int length) {
-        return new short[length];
-    }
-
-    public static Object newFloatArray7() {
-        return new float[7];
-    }
-
-    public static Object newFloatArrayMinus7() {
-        return new float[-7];
-    }
-
-    public static Object newFloatArray(int length) {
-        return new float[length];
-    }
-
-    public static Object newLongArray7() {
-        return new long[7];
-    }
-
-    public static Object newLongArrayMinus7() {
-        return new long[-7];
-    }
-
-    public static Object newLongArray(int length) {
-        return new long[length];
-    }
-
-    public static Object newDoubleArray7() {
-        return new double[7];
-    }
-
-    public static Object newDoubleArrayMinus7() {
-        return new double[-7];
-    }
-
-    public static Object newDoubleArray(int length) {
-        return new double[length];
-    }
-
-    public static Object newIntArray7() {
-        return new int[7];
-    }
-
-    public static Object newIntArrayMinus7() {
-        return new int[-7];
-    }
-
-    public static Object newIntArray(int length) {
-        return new int[length];
-    }
-
-    public static Object newByteArray7() {
-        return new byte[7];
-    }
-
-    public static Object newByteArrayMinus7() {
-        return new byte[-7];
-    }
-
-    public static Object newByteArray(int length) {
-        return new byte[length];
-    }
-
-    public static Object newStringArray7() {
-        return new String[7];
-    }
-
-    public static Object newStringArrayMinus7() {
-        return new String[-7];
-    }
-
-    public static Object newStringArray(int length) {
-        return new String[length];
-    }
-}
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/NewInstanceTest.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * 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 java.util.*;
-
-import org.junit.*;
-
-/**
- * Tests the implementation of {@code NEW}.
- */
-public class NewInstanceTest extends GraalCompilerTest {
-
-    @Override
-    protected void assertEquals(Object expected, Object actual) {
-        Assert.assertTrue(expected != null);
-        Assert.assertTrue(actual != null);
-        super.assertEquals(expected.getClass(), actual.getClass());
-        if (expected.getClass() != Object.class) {
-            try {
-                expected.getClass().getDeclaredMethod("equals", Object.class);
-                super.assertEquals(expected, actual);
-            } catch (Exception e) {
-            }
-        }
-    }
-
-    @Test
-    public void test1() {
-        test("newObject");
-        test("newBigObject");
-        test("newSomeObject");
-        test("newEmptyString");
-        test("newString", "value");
-        test("newHashMap", 31);
-        test("newRegression", true);
-    }
-
-    public static Object newObject() {
-        return new Object();
-    }
-
-    public static BigObject newBigObject() {
-        return new BigObject();
-    }
-
-    public static SomeObject newSomeObject() {
-        return new SomeObject();
-    }
-
-    public static String newEmptyString() {
-        return new String();
-    }
-
-    public static String newString(String value) {
-        return new String(value);
-    }
-
-    public static HashMap newHashMap(int initialCapacity) {
-        return new HashMap(initialCapacity);
-    }
-
-    static class SomeObject {
-        String name = "o1";
-        HashMap<String, Object> map = new HashMap<>();
-
-
-        public SomeObject() {
-            map.put(name, this.getClass());
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof SomeObject) {
-                SomeObject so = (SomeObject) obj;
-                return so.name.equals(name) && so.map.equals(map);
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            return name.hashCode();
-        }
-    }
-
-    static class BigObject {
-        Object f01;
-        Object f02;
-        Object f03;
-        Object f04;
-        Object f05;
-        Object f06;
-        Object f07;
-        Object f08;
-        Object f09;
-        Object f10;
-        Object f12;
-        Object f13;
-        Object f14;
-        Object f15;
-        Object f16;
-        Object f17;
-        Object f18;
-        Object f19;
-        Object f20;
-        Object f21;
-        Object f22;
-        Object f23;
-        Object f24;
-        Object f25;
-        Object f26;
-        Object f27;
-        Object f28;
-        Object f29;
-        Object f30;
-        Object f31;
-        Object f32;
-        Object f33;
-        Object f34;
-        Object f35;
-        Object f36;
-        Object f37;
-        Object f38;
-        Object f39;
-        Object f40;
-        Object f41;
-        Object f42;
-        Object f43;
-        Object f44;
-        Object f45;
-    }
-
-    /**
-     * Tests that an earlier bug does not occur. The issue was that the loading of the TLAB
-     * 'top' and 'end' values was being GVN'ed from each branch of the 'if' statement.
-     * This meant that the allocated B object in the true branch overwrote the allocated
-     * array. The cause is that RegisterNode was a floating node and the reads from it
-     * were UnsafeLoads which are also floating. The fix was to make RegisterNode a fixed
-     * node (which it should have been in the first place).
-     */
-    public static Object newRegression(boolean condition) {
-        Object result;
-        if (condition) {
-            Object[] arr = {0, 1, 2, 3, 4, 5};
-            result = new B();
-            for (int i = 0; i < arr.length; ++i) {
-                // If the bug exists, the values of arr will now be deadbeef values
-                // and the virtual dispatch will cause a segfault. This can result in
-                // either a VM crash or a spurious NullPointerException.
-                if (arr[i].equals(Integer.valueOf(i))) {
-                    return false;
-                }
-            }
-        } else {
-            result = new B();
-        }
-        return result;
-    }
-
-    static class B {
-        long f1 = 0xdeadbeefdeadbe01L;
-        long f2 = 0xdeadbeefdeadbe02L;
-        long f3 = 0xdeadbeefdeadbe03L;
-        long f4 = 0xdeadbeefdeadbe04L;
-        long f5 = 0xdeadbeefdeadbe05L;
-    }
-}
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/TypeCheckTest.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * 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 com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.JavaTypeProfile.*;
-import com.oracle.graal.nodes.*;
-
-/**
- * Base class for checkcast and instanceof test classes.
- */
-public abstract class TypeCheckTest extends GraalCompilerTest {
-
-    protected abstract void replaceProfile(StructuredGraph graph, JavaTypeProfile profile);
-
-    protected JavaTypeProfile currentProfile;
-
-    @Override
-    protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) {
-        boolean forceCompile = false;
-        if (currentProfile != null) {
-            replaceProfile(graph, currentProfile);
-            forceCompile = true;
-        }
-        return super.getCode(method, graph, forceCompile);
-    }
-
-    protected JavaTypeProfile profile(Class... types) {
-        if (types.length == 0) {
-            return null;
-        }
-        ProfiledType[] ptypes = new ProfiledType[types.length];
-        for (int i = 0; i < types.length; i++) {
-            ptypes[i] = new ProfiledType(runtime.getResolvedJavaType(types[i]), 1.0D / types.length);
-        }
-        return new JavaTypeProfile(0.0D, ptypes);
-    }
-
-    protected void test(String name, JavaTypeProfile profile, Object... args) {
-        assert currentProfile == null;
-        currentProfile = profile;
-        try {
-            super.test(name, args);
-        } finally {
-            currentProfile = null;
-        }
-    }
-}
--- a/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java	Wed Jul 18 10:50:57 2012 -0700
@@ -202,8 +202,8 @@
         if (base == Register.Frame) {
             assert frameRegister != null : "cannot use register " + Register.Frame + " in assembler with null register configuration";
             base = frameRegister;
-//        } else if (base == CiRegister.CallerFrame) {
-//            assert frameRegister != null : "cannot use register " + CiRegister.Frame + " in assembler with null register configuration";
+//        } else if (base == Register.CallerFrame) {
+//            assert frameRegister != null : "cannot use register " + Register.Frame + " in assembler with null register configuration";
 //            base = frameRegister;
 //            disp += targetMethod.frameSize() + 8;
         }
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,939 +0,0 @@
-/*
- * Copyright (c) 2009, 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.max.cri.xir;
-
-import static com.oracle.max.cri.xir.CiXirAssembler.XirOp.*;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.Address.*;
-import com.oracle.graal.api.meta.*;
-
-/**
- * Represents an assembler that allows a client such as the runtime system to
- * create {@link XirTemplate XIR templates}.
- */
-public abstract class CiXirAssembler {
-
-    protected XirOperand resultOperand;
-    protected boolean allocateResultOperand;
-
-    protected final List<XirInstruction> instructions = new ArrayList<>();
-    protected final List<XirLabel> labels = new ArrayList<>(5);
-    protected final List<XirParameter> parameters = new ArrayList<>(5);
-    protected final List<XirTemp> temps = new ArrayList<>(5);
-    protected final List<XirConstant> constants = new ArrayList<>(5);
-    protected final List<XirMark> marks = new ArrayList<>(5);
-
-    protected int outgoingStackSize = 0;
-
-    /**
-     * Increases by one for every {@link XirOperand operand} created.
-     */
-    protected int variableCount;
-
-    /**
-     * Marks the assembly complete.
-     */
-    protected boolean finished = true;
-
-    protected final TargetDescription target;
-
-    public CiXirAssembler(TargetDescription target) {
-        this.target = target;
-    }
-
-    public static class RuntimeCallInformation {
-        public final Object target;
-        public final boolean useInfoAfter;
-
-        public RuntimeCallInformation(Object target, boolean useInfoAfter) {
-            this.target = target;
-            this.useInfoAfter = useInfoAfter;
-        }
-    }
-
-    /**
-     * Represents additional address calculation information.
-     */
-    public static final class AddressAccessInformation {
-
-        /**
-         * The scaling factor for the scaled-index part of an address computation.
-         */
-        public final Scale scale;
-
-        /**
-         * The constant byte-sized displacement part of an address computation.
-         */
-        public final int disp;
-
-        /**
-         * Determines if the memory access through the address can trap.
-         */
-        public final boolean canTrap;
-
-        private AddressAccessInformation(boolean canTrap) {
-            this.canTrap = canTrap;
-            this.scale = Scale.Times1;
-            this.disp = 0;
-        }
-
-        private AddressAccessInformation(boolean canTrap, int disp) {
-            this.canTrap = canTrap;
-            this.scale = Scale.Times1;
-            this.disp = disp;
-        }
-
-        private AddressAccessInformation(boolean canTrap, int disp, Scale scale) {
-            this.canTrap = canTrap;
-            this.scale = scale;
-            this.disp = disp;
-        }
-    }
-
-    /**
-     * A label that is the target of a control flow instruction.
-     */
-    public static final class XirLabel {
-        public static final String TrueSuccessor = "TrueSuccessor";
-        public static final String FalseSuccessor = "FalseSuccessor";
-        public final String name;
-        public final int index;
-        /**
-         * If {@code true} the label is to an instruction in the fast path sequence, otherwise to the slow path.
-         */
-        public final boolean inline;
-
-        private XirLabel(String name, int index, boolean inline) {
-            this.name = name;
-            this.index = index;
-            this.inline = inline;
-        }
-
-        @Override
-        public String toString() {
-            return name;
-        }
-    }
-
-    /**
-     * Tagging interface that indicates that an {@link XirOperand} is a constant.
-     */
-    public interface XirConstantOperand {
-        int getIndex();
-    }
-
-    public static final XirOperand VOID = null;
-
-    /**
-     * Operands for {@link XirInstruction instructions}.
-     * There are three basic variants, {@link XirConstant constant}, {@link XirParameter parameter} and {@link XirTemp}.
-     */
-    public abstract static class XirOperand {
-
-        public final Kind kind;
-
-        /**
-         * Unique id in range {@code 0} to {@link #variableCount variableCount - 1}.
-         */
-        public final int index;
-
-        /**
-         * Value whose {@link #toString()} method provides a name for this operand.
-         */
-        public final Object name;
-
-        public XirOperand(CiXirAssembler asm, Object name, Kind kind) {
-            this.kind = kind;
-            this.name = name;
-            this.index = asm.variableCount++;
-        }
-
-        @Override
-        public String toString() {
-            return String.valueOf(name);
-        }
-
-        public String detailedToString() {
-
-            StringBuffer sb = new StringBuffer();
-
-            sb.append(name);
-            sb.append('$');
-            sb.append(kind.typeChar);
-            return sb.toString();
-        }
-    }
-
-    /**
-     * Parameters to {@link XirTemplate templates}.
-     */
-    public static class XirParameter extends XirOperand {
-        /**
-         * Unique id in range {@code 0} to {@code parameters.Size()  - 1}.
-         */
-        public final int parameterIndex;
-
-        public final boolean canBeConstant;
-
-        XirParameter(CiXirAssembler asm, String name, Kind kind, boolean canBeConstant) {
-            super(asm, name, kind);
-            this.parameterIndex = asm.parameters.size();
-            this.canBeConstant = canBeConstant;
-            asm.parameters.add(this);
-        }
-
-    }
-
-    public static class XirConstantParameter extends XirParameter implements XirConstantOperand {
-        XirConstantParameter(CiXirAssembler asm, String name, Kind kind) {
-            super(asm, name, kind, true);
-        }
-
-        public int getIndex() {
-            return index;
-        }
-    }
-
-    public static class XirVariableParameter extends XirParameter {
-        XirVariableParameter(CiXirAssembler asm, String name, Kind kind, boolean canBeConstant) {
-            super(asm, name, kind, canBeConstant);
-        }
-    }
-
-    public static class XirConstant extends XirOperand implements XirConstantOperand {
-        public final Constant value;
-
-        XirConstant(CiXirAssembler asm, Constant value) {
-            super(asm, value, value.kind);
-            this.value = value;
-        }
-
-        public int getIndex() {
-            return index;
-        }
-    }
-
-    public static class XirTemp extends XirOperand {
-        public final boolean reserve;
-
-        XirTemp(CiXirAssembler asm, String name, Kind kind, boolean reserve) {
-            super(asm, name, kind);
-            this.reserve = reserve;
-        }
-    }
-
-    public static class XirRegister extends XirTemp {
-        public final Value register;
-
-        XirRegister(CiXirAssembler asm, String name, RegisterValue register, boolean reserve) {
-            super(asm, name, register.kind, reserve);
-            this.register = register;
-        }
-    }
-
-    /**
-     * Start a new assembly with no initial {@link #resultOperand result operand}.
-     */
-    public void restart() {
-        reset();
-        resultOperand = null;
-    }
-
-    /**
-     * Start a new assembly with a {@link #resultOperand result operand} of type {@code kind}.
-     * @param kind the result kind
-     * @return an {@code XirOperand} for the result operand
-     */
-    public XirOperand restart(Kind kind) {
-        reset();
-        resultOperand = new XirTemp(this, "result", kind, true);
-        allocateResultOperand = true;
-        return resultOperand;
-    }
-
-    /**
-     * Reset the state of the class to the initial conditions to facilitate a new assembly.
-     */
-    private void reset() {
-        assert finished : "must be finished before!";
-        variableCount = 0;
-        allocateResultOperand = false;
-        finished = false;
-        instructions.clear();
-        labels.clear();
-        parameters.clear();
-        temps.clear();
-        constants.clear();
-        marks.clear();
-        outgoingStackSize = 0;
-    }
-
-    /**
-     * Represents an XIR instruction, characterized by an {@link XirOp operation}, a {@link Kind kind}, an optional {@link XirOperand result}, a variable number of {@link XirOperand arguments},
-     * and some optional instruction-specific state. The {@link #x}, {@link #y} and {@link #z} methods are convenient ways to access the first, second and third
-     * arguments, respectively. Only {@link XirOp#CallRuntime} instructions can have more than three arguments.
-     *
-     */
-    public static final class XirInstruction {
-        /**
-         * The {@link Kind kind} of values the instruction operates on.
-         */
-        public final Kind kind;
-        /**
-         * The {@link XirOp operation}.
-         */
-        public final XirOp op;
-        /**
-         * The result, if any.
-         */
-        public final XirOperand result;
-        /**
-         * The arguments.
-         */
-        public final XirOperand[] arguments;
-        /**
-         * Arbitrary additional data associated with the instruction.
-         */
-        public final Object extra;
-
-        public XirInstruction(Kind kind, XirOp op, XirOperand result, XirOperand... arguments) {
-            this(kind, null, op, result, arguments);
-        }
-
-        public XirInstruction(Kind kind, Object extra, XirOp op, XirOperand result, XirOperand... arguments) {
-            this.extra = extra;
-            this.kind = kind;
-            this.op = op;
-            this.result = result;
-            this.arguments = arguments;
-        }
-
-        public XirOperand x() {
-            assert arguments.length > 0 : "no x operand for this instruction";
-            return arguments[0];
-        }
-
-        public XirOperand y() {
-            assert arguments.length > 1 : "no y operand for this instruction";
-            return arguments[1];
-        }
-
-        public XirOperand z() {
-            assert arguments.length > 2 : "no z operand for this instruction";
-            return arguments[2];
-        }
-
-        @Override
-        public String toString() {
-            StringBuffer sb = new StringBuffer();
-
-            if (result != null) {
-                sb.append(result.toString());
-                sb.append(" = ");
-            }
-
-            sb.append(op.name());
-
-            if (kind != Kind.Void) {
-                sb.append('$');
-                sb.append(kind.typeChar);
-            }
-
-            if (arguments != null && arguments.length > 0) {
-                sb.append("(");
-
-                for (int i = 0; i < arguments.length; i++) {
-                    if (i != 0) {
-                        sb.append(", ");
-                    }
-                    sb.append(arguments[i]);
-                }
-
-                sb.append(")");
-            }
-
-            if (extra != null) {
-                sb.append(" ");
-                sb.append(extra);
-            }
-
-            return sb.toString();
-        }
-    }
-
-    /**
-     * These marks let the RiXirGenerator mark positions in the generated native code and bring them in relationship with on another.
-     * This is necessary for code patching, etc.
-     */
-    public static class XirMark {
-        public final XirMark[] references;
-        public final Object id;
-
-        // special mark used to refer to the actual call site of an invoke
-        public static final XirMark CALLSITE = new XirMark(null);
-
-        public XirMark(Object id, XirMark... references) {
-            this.id = id;
-            this.references = references;
-        }
-    }
-
-    /**
-     * The set of opcodes for XIR instructions.
-     * {@link XirInstruction} defines {@code x}, {@code y} and {@code z} as the first, second and third arguments, respectively.
-     * We use these mnemonics, plus {@code args} for the complete set of arguments, {@code r} for the result, and {@code extra}
-     * for the instruction-specific extra data, in the opcode specifications. Note that the opcodes that operate on values do not directly
-     * specify the size (kind) of the data operated on;  this is is encoded in {@link XirInstruction#kind}.
-     * Note: If the instruction kind differs from the argument/result kinds, the behavior is undefined.
-     *
-     */
-    public enum XirOp {
-        /**
-         * Move {@code x} to {@code r}.
-         */
-        Mov,
-        /**
-         * Add {@code y} to {@code x} and put the result in {@code r}.
-         */
-        Add,
-        /**
-         * Subtract {@code y} from {@code x} and put the result in {@code r}.
-         */
-        Sub,
-        /**
-         * Divide {@code y} by {@code x} and put the result in {@code r}.
-         */
-        Div,
-        /**
-         * Multiply {@code y} by {@code x} and put the result in {@code r}.
-         */
-        Mul,
-        /**
-         * {@code y} modulus {@code x} and put the result in {@code r}.
-         */
-        Mod,
-        /**
-         * Shift  {@code y} left by {@code x} and put the result in {@code r}.
-         */
-        Shl,
-        /**
-         * Arithmetic shift  {@code y} right by {@code x} and put the result in {@code r}.
-         */
-        Sar,
-        /**
-         * Shift  {@code y} right by {@code x} and put the result in {@code r}.
-         */
-        Shr,
-        /**
-         * And {@code y} by {@code x} and put the result in {@code r}.
-         */
-        And,
-        /**
-         * Or {@code y} by {@code x} and put the result in {@code r}.
-         */
-        Or,
-        /**
-         * Exclusive Or {@code y} by {@code x} and put the result in {@code r}.
-         */
-        Xor,
-        /**
-         * Null check on {@code x}.
-         */
-        NullCheck,
-        /**
-         * Load value at address {@code x} and put the result in {@code r}.
-         */
-        PointerLoad,
-        /**
-         * Store {@code y} at address {@code x}.
-         */
-        PointerStore,
-        /**
-         * Load value at an effective address defined by base {@code x} and either a scaled index {@code y} plus displacement
-         * or an offset {@code y} and put the result in {@code r}.
-         */
-        PointerLoadDisp,
-        /**
-         * Load an effective address defined by base {@code x} and either a scaled index {@code y} plus displacement
-         * or an offset {@code y} and put the result in {@code r}.
-         */
-        LoadEffectiveAddress,
-        /**
-         * Store {@code z} at address defined by base {@code x} and index {@code y}.
-         */
-        PointerStoreDisp,
-        /**
-         * Repeat move from {@code x} to {@code y} using {@code z} words.
-         */
-        RepeatMoveWords,
-        /**
-         * Repeat move from {@code x} to {@code y} using {@code z} words.
-         */
-        RepeatMoveBytes,
-        /**
-         * Compare value at at address {@code x} with value in {@code y} and store value {@code z} at address {@code x}
-         * if it was equal to {@code y}.
-         */
-        PointerCAS,
-        /**
-         * Call the {@link JavaMethod} defined by {@code extra}  with {@code args} and put the result in {@code r}.
-         */
-        CallRuntime,
-        /**
-         * Transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
-         */
-        Jmp,
-       /**
-         * If {@code x == y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
-         */
-        Jeq,
-        /**
-         * If {@code x != y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
-         */
-        Jneq,
-        /**
-         * If {@code x > y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
-         */
-        Jgt,
-        /**
-         * If {@code x >= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
-         */
-        Jgteq,
-        /**
-         * If {@code x unsigned >= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
-         */
-        Jugteq,
-        /**
-         * If {@code x < y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
-         */
-        Jlt,
-        /**
-         * If {@code x <= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
-         */
-        Jlteq,
-        /**
-         * Decreases the input by one and jumps to the target if the input is not 0.
-         */
-        DecAndJumpNotZero,
-        /**
-         * If bit designated by {@code z} at effective address defined by base {@code x} and offset {@code y}
-         * is set transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
-         */
-        Jbset,
-        /**
-         * Bind the {@link XirLabel label} identified by {@code extra} to the current instruction and update any references to it.
-         * A label may be bound more than once to the same location.
-         */
-        Bind,
-        /**
-         * Record a safepoint.
-         */
-        Safepoint,
-        /**
-         * Pushes a value onto the stack.
-         */
-        Push,
-        /**
-         * Pops a value from the stack.
-         */
-        Pop,
-        /**
-         * Marks a position in the generated native code.
-         */
-        Mark,
-        /**
-         * Load instruction pointer of the next instruction in a destination register.
-         */
-        Here,
-        /**
-         * Inserts nop instructions, with the given size in bytes.
-         */
-        Nop,
-        /**
-         * This instruction should never be reached, this is useful for debugging purposes.
-         */
-         ShouldNotReachHere
-    }
-
-    public/*private*/ void append(XirInstruction xirInstruction) {
-        assert !finished : "no instructions can be added to finished template";
-        instructions.add(xirInstruction);
-    }
-
-    public XirLabel createInlineLabel(String name) {
-        final XirLabel result = new XirLabel(name, this.labels.size(), true);
-        labels.add(result);
-        return result;
-    }
-
-    public XirLabel createOutOfLineLabel(String name) {
-        final XirLabel result = new XirLabel(name, this.labels.size(), false);
-        labels.add(result);
-        return result;
-    }
-
-    public void mov(XirOperand result, XirOperand a) {
-        append(new XirInstruction(result.kind, Mov, result, a));
-    }
-
-    public void add(XirOperand result, XirOperand a, XirOperand b) {
-        append(new XirInstruction(result.kind, Add, result, a, b));
-    }
-
-    public void sub(XirOperand result, XirOperand a, XirOperand b) {
-        append(new XirInstruction(result.kind, Sub, result, a, b));
-    }
-
-    public void div(XirOperand result, XirOperand a, XirOperand b) {
-        append(new XirInstruction(result.kind, Div, result, a, b));
-    }
-
-    public void mul(XirOperand result, XirOperand a, XirOperand b) {
-        append(new XirInstruction(result.kind, Mul, result, a, b));
-    }
-
-    public void mod(XirOperand result, XirOperand a, XirOperand b) {
-        append(new XirInstruction(result.kind, Mod, result, a, b));
-    }
-
-    public void shl(XirOperand result, XirOperand a, XirOperand b) {
-        append(new XirInstruction(result.kind, Shl, result, a, b));
-    }
-
-    public void shr(XirOperand result, XirOperand a, XirOperand b) {
-        append(new XirInstruction(result.kind, Shr, result, a, b));
-    }
-
-    public void and(XirOperand result, XirOperand a, XirOperand b) {
-        append(new XirInstruction(result.kind, And, result, a, b));
-    }
-
-    public void or(XirOperand result, XirOperand a, XirOperand b) {
-        append(new XirInstruction(result.kind, Or, result, a, b));
-    }
-
-    public void xor(XirOperand result, XirOperand a, XirOperand b) {
-        append(new XirInstruction(result.kind, Xor, result, a, b));
-    }
-
-    public void nullCheck(XirOperand pointer) {
-        append(new XirInstruction(Kind.Object, NullCheck, VOID, pointer));
-    }
-
-    public void pload(Kind kind, XirOperand result, XirOperand pointer, boolean canTrap) {
-        append(new XirInstruction(kind, canTrap, PointerLoad, result, pointer));
-    }
-
-    public void pstore(Kind kind, XirOperand pointer, XirOperand value, boolean canTrap) {
-        append(new XirInstruction(kind, canTrap, PointerStore, null, pointer, value));
-    }
-
-    public void pload(Kind kind, XirOperand result, XirOperand pointer, XirOperand offset, boolean canTrap) {
-        append(new XirInstruction(kind, new AddressAccessInformation(canTrap), PointerLoadDisp, result, pointer, offset));
-    }
-
-    public void pstore(Kind kind, XirOperand pointer, XirOperand offset, XirOperand value, boolean canTrap) {
-        append(new XirInstruction(kind, new AddressAccessInformation(canTrap), PointerStoreDisp, VOID, pointer, offset, value));
-    }
-
-    public void pload(Kind kind, XirOperand result, XirOperand pointer, XirOperand index, int disp, Scale scale,  boolean canTrap) {
-        append(new XirInstruction(kind, new AddressAccessInformation(canTrap, disp, scale), PointerLoadDisp, result, pointer, index));
-    }
-
-    public void lea(XirOperand result, XirOperand pointer, XirOperand index, int disp, Scale scale) {
-        append(new XirInstruction(target.wordKind, new AddressAccessInformation(false, disp, scale), LoadEffectiveAddress, result, pointer, index));
-    }
-
-    public void repmov(XirOperand src, XirOperand dest, XirOperand length) {
-        append(new XirInstruction(target.wordKind, null, RepeatMoveWords, null, src, dest, length));
-    }
-
-    public void here(XirOperand dst) {
-        append(new XirInstruction(target.wordKind, null, Here, dst));
-    }
-
-    public void repmovb(XirOperand src, XirOperand dest, XirOperand length) {
-        append(new XirInstruction(target.wordKind, null, RepeatMoveBytes, null, src, dest, length));
-    }
-
-    public void pstore(Kind kind, XirOperand pointer, XirOperand index, XirOperand value, int disp, Scale scale, boolean canTrap) {
-        append(new XirInstruction(kind, new AddressAccessInformation(canTrap, disp, scale), PointerStoreDisp, VOID, pointer, index, value));
-    }
-
-    public void pcas(Kind kind, XirOperand result, XirOperand pointer, XirOperand newValue, XirOperand oldValue) {
-        append(new XirInstruction(kind, null, PointerCAS, result, pointer, newValue, oldValue));
-    }
-
-    public void jmp(XirLabel l) {
-        append(new XirInstruction(Kind.Void, l, Jmp, null));
-    }
-
-    public void decAndJumpNotZero(XirLabel l, XirOperand val) {
-        append(new XirInstruction(Kind.Void, l, DecAndJumpNotZero, null, val));
-    }
-
-    public void jmpRuntime(Object rt) {
-        append(new XirInstruction(Kind.Void, rt, Jmp, null));
-    }
-
-    public void jeq(XirLabel l, XirOperand a, XirOperand b) {
-        jcc(Jeq, l, a, b);
-    }
-
-    private void jcc(XirOp op, XirLabel l, XirOperand a, XirOperand b) {
-        append(new XirInstruction(Kind.Void, l, op, null, a, b));
-    }
-
-    public void jneq(XirLabel l, XirOperand a, XirOperand b) {
-        jcc(Jneq, l, a, b);
-    }
-
-    public void jgt(XirLabel l, XirOperand a, XirOperand b) {
-        jcc(Jgt, l, a, b);
-    }
-
-    public void jgteq(XirLabel l, XirOperand a, XirOperand b) {
-        jcc(Jgteq, l, a, b);
-    }
-
-    public void jugteq(XirLabel l, XirOperand a, XirOperand b) {
-        jcc(Jugteq, l, a, b);
-    }
-
-    public void jlt(XirLabel l, XirOperand a, XirOperand b) {
-        jcc(Jlt, l, a, b);
-    }
-
-    public void jlteq(XirLabel l, XirOperand a, XirOperand b) {
-        jcc(Jlteq, l, a, b);
-    }
-
-    public void jbset(XirLabel l, XirOperand a, XirOperand b, XirOperand c) {
-        append(new XirInstruction(Kind.Void, l, Jbset, null, a, b, c));
-    }
-
-    public void bindInline(XirLabel l) {
-        assert l.inline;
-        append(new XirInstruction(Kind.Void, l, Bind, null));
-    }
-
-    public void bindOutOfLine(XirLabel l) {
-        assert !l.inline;
-        append(new XirInstruction(Kind.Void, l, Bind, null));
-    }
-
-    public void safepoint() {
-        append(new XirInstruction(Kind.Void, null, Safepoint, null));
-    }
-
-    public void push(XirOperand value) {
-        append(new XirInstruction(Kind.Void, Push, VOID, value));
-    }
-
-    public void pop(XirOperand result) {
-        append(new XirInstruction(result.kind, Pop, result));
-    }
-
-    public XirMark mark(Object id, XirMark... references) {
-        XirMark mark = new XirMark(id, references);
-        marks.add(mark);
-        append(new XirInstruction(Kind.Void, mark, Mark, null));
-        return mark;
-    }
-
-    public void nop(int size) {
-        append(new XirInstruction(Kind.Void, size, Nop, null));
-    }
-
-    public void shouldNotReachHere() {
-        append(new XirInstruction(Kind.Void, null, ShouldNotReachHere, null));
-    }
-
-    public void shouldNotReachHere(String message) {
-        append(new XirInstruction(Kind.Void, message, ShouldNotReachHere, null));
-    }
-
-    public void callRuntime(Object rt, XirOperand result, XirOperand... args) {
-        callRuntime(rt, result, false, args);
-    }
-
-    public void callRuntime(Object rt, XirOperand result, boolean useInfoAfter, XirOperand... args) {
-        Kind resultKind = result == null ? Kind.Void : result.kind;
-        append(new XirInstruction(resultKind, new RuntimeCallInformation(rt, useInfoAfter), CallRuntime, result, args));
-    }
-
-    /**
-     * Terminates the assembly, checking invariants, in particular that {@link #resultOperand} is set, and setting {@link #finished} to {@code true}.
-     */
-    private void end() {
-        assert !finished : "template may only be finished once!";
-        assert resultOperand != null : "result operand should be set";
-        finished = true;
-    }
-
-    /**
-     * Creates an {@link XirVariableParameter variable input parameter}  of given name and {@link Kind kind}.
-     * @param name a name for the parameter
-     * @param kind the parameter kind
-     * @return the  {@link XirVariableParameter}
-     */
-    public XirVariableParameter createInputParameter(String name, Kind kind, boolean canBeConstant) {
-        assert !finished;
-        return new XirVariableParameter(this, name, kind, canBeConstant);
-    }
-
-    public XirVariableParameter createInputParameter(String name, Kind kind) {
-        return createInputParameter(name, kind, false);
-    }
-
-    /**
-     * Creates an {@link XirConstantParameter constant input parameter}  of given name and {@link Kind kind}.
-     * @param name a name for the parameter
-     * @param kind the parameter kind
-     * @return the  {@link XirConstantParameter}
-     */
-    public XirConstantParameter createConstantInputParameter(String name, Kind kind) {
-        assert !finished;
-        return new XirConstantParameter(this, name, kind);
-    }
-
-    public XirConstant createConstant(Constant constant) {
-        assert !finished;
-        XirConstant temp = new XirConstant(this, constant);
-        constants.add(temp);
-        return temp;
-    }
-
-    public XirOperand createTemp(String name, Kind kind) {
-        assert !finished;
-        XirTemp temp = new XirTemp(this, name, kind, true);
-        temps.add(temp);
-        return temp;
-    }
-
-    public XirOperand createRegister(String name, Kind kind, Register register) {
-        return createRegister(name, kind, register, false);
-    }
-
-    public XirOperand createRegisterTemp(String name, Kind kind, Register register) {
-        return createRegister(name, kind, register, true);
-    }
-
-    private XirOperand createRegister(String name, Kind kind, Register register, boolean reserve) {
-        assert !finished;
-        XirRegister fixed = new XirRegister(this, name, register.asValue(kind), reserve);
-        temps.add(fixed);
-        return fixed;
-    }
-
-    public XirParameter getParameter(String name) {
-        for (XirParameter param : parameters) {
-            if (param.name.toString().equals(name)) {
-                return param;
-            }
-        }
-        throw new IllegalArgumentException("no parameter: " + name);
-    }
-
-    public XirTemp getTemp(String name) {
-        for (XirTemp temp : temps) {
-            if (temp.name.toString().equals(name)) {
-                return temp;
-            }
-        }
-        throw new IllegalArgumentException("no temp: " + name);
-    }
-
-    public XirConstant i(int v) {
-        return createConstant(Constant.forInt(v));
-    }
-
-    public XirConstant l(long v) {
-        return createConstant(Constant.forLong(v));
-    }
-
-    public XirConstant b(boolean v) {
-        return createConstant(Constant.forBoolean(v));
-    }
-
-    public XirConstant o(Object obj) {
-        return createConstant(Constant.forObject(obj));
-    }
-
-    public void reserveOutgoingStack(int size) {
-        outgoingStackSize = Math.max(outgoingStackSize, size);
-    }
-
-    /**
-     * Finishes the assembly of a non-stub template, providing the {@link #resultOperand} and constructs the {@link XirTemplate}.
-     * @param result the {@link XirOperand} to be set as the {@link #resultOperand}
-     * @param name the name of the template
-     * @return the generated template
-     */
-    public XirTemplate finishTemplate(XirOperand result, String name) {
-        assert this.resultOperand == null;
-        assert result != null;
-        this.resultOperand = result;
-        final XirTemplate template = buildTemplate(name, false);
-        end();
-        return template;
-    }
-
-    /**
-     * Finishes the assembly of a non-stub template and constructs the {@link XirTemplate}.
-     * @param name the name of the template
-     * @return the generated template
-     */
-    public XirTemplate finishTemplate(String name) {
-        final XirTemplate template = buildTemplate(name, false);
-        end();
-        return template;
-    }
-
-    /**
-     * Finishes the assembly of a {@link XirTemplate.GlobalFlags#GLOBAL_STUB stub} and constructs the {@link XirTemplate}.
-     * @param name the name of the template
-     * @return the generated template
-     */
-    public XirTemplate finishStub(String name) {
-        final XirTemplate template = buildTemplate(name, true);
-        end();
-        return template;
-    }
-
-    /**
-     * Builds the {@link XirTemplate} from the assembly state in this object.
-     * The actual assembly is dependent on the target architecture and implemented
-     * in a concrete subclass.
-     * @param name the name of the template
-     * @param isStub {@code true} if the template represents a {@link XirTemplate.GlobalFlags#GLOBAL_STUB stub}
-     * @return the generated template
-     */
-    protected abstract XirTemplate buildTemplate(String name, boolean isStub);
-
-    public abstract CiXirAssembler copy();
-
-}
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java	Thu Jul 05 11:48:30 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2009, 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.max.cri.xir;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.JavaType.*;
-
-/**
- * Represents the interface through which the compiler requests the XIR for a given bytecode from the runtime system.
- */
-public interface RiXirGenerator {
-
-    XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, JavaMethod method);
-
-    XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, JavaMethod method, boolean megamorph);
-
-    XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, JavaMethod method);
-
-    XirSnippet genInvokeStatic(XirSite site, JavaMethod method);
-
-    XirSnippet genMonitorEnter(XirSite site, XirArgument receiver, XirArgument lockAddress);
-
-    XirSnippet genMonitorExit(XirSite site, XirArgument receiver, XirArgument lockAddress);
-
-    XirSnippet genNewInstance(XirSite site, JavaType type);
-
-    XirSnippet genNewArray(XirSite site, XirArgument length, Kind elementKind, JavaType componentType, JavaType arrayType);
-
-    XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, JavaType type);
-
-    XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile);
-
-    XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile);
-
-    XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, ResolvedJavaType type, JavaTypeProfile profile);
-
-    /**
-     * Generates code that checks that the {@linkplain Representation#ObjectHub hub} of
-     * an object is identical to a given hub constant. In pseudo code:
-     * <pre>
-     *     if (object.getHub() != hub) {
-     *       jump(falseSuccessor)
-     *     }
-     * </pre>
-     * This snippet should only be used when the object is guaranteed not to be null.
-     */
-    XirSnippet genTypeBranch(XirSite site, XirArgument thisHub, XirArgument otherHub, JavaType type);
-
-    /**
-     * Initializes the XIR generator for the given XIR assembler.
-     *
-     * @param asm the XIR assembler
-     */
-    void initialize(CiXirAssembler asm);
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirAssembler.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,939 @@
+/*
+ * Copyright (c) 2009, 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.max.cri.xir;
+
+import static com.oracle.max.cri.xir.XirAssembler.XirOp.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.Address.*;
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Represents an assembler that allows a client such as the runtime system to
+ * create {@link XirTemplate XIR templates}.
+ */
+public abstract class XirAssembler {
+
+    protected XirOperand resultOperand;
+    protected boolean allocateResultOperand;
+
+    protected final List<XirInstruction> instructions = new ArrayList<>();
+    protected final List<XirLabel> labels = new ArrayList<>(5);
+    protected final List<XirParameter> parameters = new ArrayList<>(5);
+    protected final List<XirTemp> temps = new ArrayList<>(5);
+    protected final List<XirConstant> constants = new ArrayList<>(5);
+    protected final List<XirMark> marks = new ArrayList<>(5);
+
+    protected int outgoingStackSize = 0;
+
+    /**
+     * Increases by one for every {@link XirOperand operand} created.
+     */
+    protected int variableCount;
+
+    /**
+     * Marks the assembly complete.
+     */
+    protected boolean finished = true;
+
+    protected final TargetDescription target;
+
+    public XirAssembler(TargetDescription target) {
+        this.target = target;
+    }
+
+    public static class RuntimeCallInformation {
+        public final Object target;
+        public final boolean useInfoAfter;
+
+        public RuntimeCallInformation(Object target, boolean useInfoAfter) {
+            this.target = target;
+            this.useInfoAfter = useInfoAfter;
+        }
+    }
+
+    /**
+     * Represents additional address calculation information.
+     */
+    public static final class AddressAccessInformation {
+
+        /**
+         * The scaling factor for the scaled-index part of an address computation.
+         */
+        public final Scale scale;
+
+        /**
+         * The constant byte-sized displacement part of an address computation.
+         */
+        public final int disp;
+
+        /**
+         * Determines if the memory access through the address can trap.
+         */
+        public final boolean canTrap;
+
+        private AddressAccessInformation(boolean canTrap) {
+            this.canTrap = canTrap;
+            this.scale = Scale.Times1;
+            this.disp = 0;
+        }
+
+        private AddressAccessInformation(boolean canTrap, int disp) {
+            this.canTrap = canTrap;
+            this.scale = Scale.Times1;
+            this.disp = disp;
+        }
+
+        private AddressAccessInformation(boolean canTrap, int disp, Scale scale) {
+            this.canTrap = canTrap;
+            this.scale = scale;
+            this.disp = disp;
+        }
+    }
+
+    /**
+     * A label that is the target of a control flow instruction.
+     */
+    public static final class XirLabel {
+        public static final String TrueSuccessor = "TrueSuccessor";
+        public static final String FalseSuccessor = "FalseSuccessor";
+        public final String name;
+        public final int index;
+        /**
+         * If {@code true} the label is to an instruction in the fast path sequence, otherwise to the slow path.
+         */
+        public final boolean inline;
+
+        private XirLabel(String name, int index, boolean inline) {
+            this.name = name;
+            this.index = index;
+            this.inline = inline;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+
+    /**
+     * Tagging interface that indicates that an {@link XirOperand} is a constant.
+     */
+    public interface XirConstantOperand {
+        int getIndex();
+    }
+
+    public static final XirOperand VOID = null;
+
+    /**
+     * Operands for {@link XirInstruction instructions}.
+     * There are three basic variants, {@link XirConstant constant}, {@link XirParameter parameter} and {@link XirTemp}.
+     */
+    public abstract static class XirOperand {
+
+        public final Kind kind;
+
+        /**
+         * Unique id in range {@code 0} to {@link #variableCount variableCount - 1}.
+         */
+        public final int index;
+
+        /**
+         * Value whose {@link #toString()} method provides a name for this operand.
+         */
+        public final Object name;
+
+        public XirOperand(XirAssembler asm, Object name, Kind kind) {
+            this.kind = kind;
+            this.name = name;
+            this.index = asm.variableCount++;
+        }
+
+        @Override
+        public String toString() {
+            return String.valueOf(name);
+        }
+
+        public String detailedToString() {
+
+            StringBuffer sb = new StringBuffer();
+
+            sb.append(name);
+            sb.append('$');
+            sb.append(kind.typeChar);
+            return sb.toString();
+        }
+    }
+
+    /**
+     * Parameters to {@link XirTemplate templates}.
+     */
+    public static class XirParameter extends XirOperand {
+        /**
+         * Unique id in range {@code 0} to {@code parameters.Size()  - 1}.
+         */
+        public final int parameterIndex;
+
+        public final boolean canBeConstant;
+
+        XirParameter(XirAssembler asm, String name, Kind kind, boolean canBeConstant) {
+            super(asm, name, kind);
+            this.parameterIndex = asm.parameters.size();
+            this.canBeConstant = canBeConstant;
+            asm.parameters.add(this);
+        }
+
+    }
+
+    public static class XirConstantParameter extends XirParameter implements XirConstantOperand {
+        XirConstantParameter(XirAssembler asm, String name, Kind kind) {
+            super(asm, name, kind, true);
+        }
+
+        public int getIndex() {
+            return index;
+        }
+    }
+
+    public static class XirVariableParameter extends XirParameter {
+        XirVariableParameter(XirAssembler asm, String name, Kind kind, boolean canBeConstant) {
+            super(asm, name, kind, canBeConstant);
+        }
+    }
+
+    public static class XirConstant extends XirOperand implements XirConstantOperand {
+        public final Constant value;
+
+        XirConstant(XirAssembler asm, Constant value) {
+            super(asm, value, value.kind);
+            this.value = value;
+        }
+
+        public int getIndex() {
+            return index;
+        }
+    }
+
+    public static class XirTemp extends XirOperand {
+        public final boolean reserve;
+
+        XirTemp(XirAssembler asm, String name, Kind kind, boolean reserve) {
+            super(asm, name, kind);
+            this.reserve = reserve;
+        }
+    }
+
+    public static class XirRegister extends XirTemp {
+        public final Value register;
+
+        XirRegister(XirAssembler asm, String name, RegisterValue register, boolean reserve) {
+            super(asm, name, register.kind, reserve);
+            this.register = register;
+        }
+    }
+
+    /**
+     * Start a new assembly with no initial {@link #resultOperand result operand}.
+     */
+    public void restart() {
+        reset();
+        resultOperand = null;
+    }
+
+    /**
+     * Start a new assembly with a {@link #resultOperand result operand} of type {@code kind}.
+     * @param kind the result kind
+     * @return an {@code XirOperand} for the result operand
+     */
+    public XirOperand restart(Kind kind) {
+        reset();
+        resultOperand = new XirTemp(this, "result", kind, true);
+        allocateResultOperand = true;
+        return resultOperand;
+    }
+
+    /**
+     * Reset the state of the class to the initial conditions to facilitate a new assembly.
+     */
+    private void reset() {
+        assert finished : "must be finished before!";
+        variableCount = 0;
+        allocateResultOperand = false;
+        finished = false;
+        instructions.clear();
+        labels.clear();
+        parameters.clear();
+        temps.clear();
+        constants.clear();
+        marks.clear();
+        outgoingStackSize = 0;
+    }
+
+    /**
+     * Represents an XIR instruction, characterized by an {@link XirOp operation}, a {@link Kind kind}, an optional {@link XirOperand result}, a variable number of {@link XirOperand arguments},
+     * and some optional instruction-specific state. The {@link #x}, {@link #y} and {@link #z} methods are convenient ways to access the first, second and third
+     * arguments, respectively. Only {@link XirOp#CallRuntime} instructions can have more than three arguments.
+     *
+     */
+    public static final class XirInstruction {
+        /**
+         * The {@link Kind kind} of values the instruction operates on.
+         */
+        public final Kind kind;
+        /**
+         * The {@link XirOp operation}.
+         */
+        public final XirOp op;
+        /**
+         * The result, if any.
+         */
+        public final XirOperand result;
+        /**
+         * The arguments.
+         */
+        public final XirOperand[] arguments;
+        /**
+         * Arbitrary additional data associated with the instruction.
+         */
+        public final Object extra;
+
+        public XirInstruction(Kind kind, XirOp op, XirOperand result, XirOperand... arguments) {
+            this(kind, null, op, result, arguments);
+        }
+
+        public XirInstruction(Kind kind, Object extra, XirOp op, XirOperand result, XirOperand... arguments) {
+            this.extra = extra;
+            this.kind = kind;
+            this.op = op;
+            this.result = result;
+            this.arguments = arguments;
+        }
+
+        public XirOperand x() {
+            assert arguments.length > 0 : "no x operand for this instruction";
+            return arguments[0];
+        }
+
+        public XirOperand y() {
+            assert arguments.length > 1 : "no y operand for this instruction";
+            return arguments[1];
+        }
+
+        public XirOperand z() {
+            assert arguments.length > 2 : "no z operand for this instruction";
+            return arguments[2];
+        }
+
+        @Override
+        public String toString() {
+            StringBuffer sb = new StringBuffer();
+
+            if (result != null) {
+                sb.append(result.toString());
+                sb.append(" = ");
+            }
+
+            sb.append(op.name());
+
+            if (kind != Kind.Void) {
+                sb.append('$');
+                sb.append(kind.typeChar);
+            }
+
+            if (arguments != null && arguments.length > 0) {
+                sb.append("(");
+
+                for (int i = 0; i < arguments.length; i++) {
+                    if (i != 0) {
+                        sb.append(", ");
+                    }
+                    sb.append(arguments[i]);
+                }
+
+                sb.append(")");
+            }
+
+            if (extra != null) {
+                sb.append(" ");
+                sb.append(extra);
+            }
+
+            return sb.toString();
+        }
+    }
+
+    /**
+     * These marks let the {@link XirGenerator} mark positions in the generated native code and bring them in relationship with on another.
+     * This is necessary for code patching, etc.
+     */
+    public static class XirMark {
+        public final XirMark[] references;
+        public final Object id;
+
+        // special mark used to refer to the actual call site of an invoke
+        public static final XirMark CALLSITE = new XirMark(null);
+
+        public XirMark(Object id, XirMark... references) {
+            this.id = id;
+            this.references = references;
+        }
+    }
+
+    /**
+     * The set of opcodes for XIR instructions.
+     * {@link XirInstruction} defines {@code x}, {@code y} and {@code z} as the first, second and third arguments, respectively.
+     * We use these mnemonics, plus {@code args} for the complete set of arguments, {@code r} for the result, and {@code extra}
+     * for the instruction-specific extra data, in the opcode specifications. Note that the opcodes that operate on values do not directly
+     * specify the size (kind) of the data operated on;  this is is encoded in {@link XirInstruction#kind}.
+     * Note: If the instruction kind differs from the argument/result kinds, the behavior is undefined.
+     *
+     */
+    public enum XirOp {
+        /**
+         * Move {@code x} to {@code r}.
+         */
+        Mov,
+        /**
+         * Add {@code y} to {@code x} and put the result in {@code r}.
+         */
+        Add,
+        /**
+         * Subtract {@code y} from {@code x} and put the result in {@code r}.
+         */
+        Sub,
+        /**
+         * Divide {@code y} by {@code x} and put the result in {@code r}.
+         */
+        Div,
+        /**
+         * Multiply {@code y} by {@code x} and put the result in {@code r}.
+         */
+        Mul,
+        /**
+         * {@code y} modulus {@code x} and put the result in {@code r}.
+         */
+        Mod,
+        /**
+         * Shift  {@code y} left by {@code x} and put the result in {@code r}.
+         */
+        Shl,
+        /**
+         * Arithmetic shift  {@code y} right by {@code x} and put the result in {@code r}.
+         */
+        Sar,
+        /**
+         * Shift  {@code y} right by {@code x} and put the result in {@code r}.
+         */
+        Shr,
+        /**
+         * And {@code y} by {@code x} and put the result in {@code r}.
+         */
+        And,
+        /**
+         * Or {@code y} by {@code x} and put the result in {@code r}.
+         */
+        Or,
+        /**
+         * Exclusive Or {@code y} by {@code x} and put the result in {@code r}.
+         */
+        Xor,
+        /**
+         * Null check on {@code x}.
+         */
+        NullCheck,
+        /**
+         * Load value at address {@code x} and put the result in {@code r}.
+         */
+        PointerLoad,
+        /**
+         * Store {@code y} at address {@code x}.
+         */
+        PointerStore,
+        /**
+         * Load value at an effective address defined by base {@code x} and either a scaled index {@code y} plus displacement
+         * or an offset {@code y} and put the result in {@code r}.
+         */
+        PointerLoadDisp,
+        /**
+         * Load an effective address defined by base {@code x} and either a scaled index {@code y} plus displacement
+         * or an offset {@code y} and put the result in {@code r}.
+         */
+        LoadEffectiveAddress,
+        /**
+         * Store {@code z} at address defined by base {@code x} and index {@code y}.
+         */
+        PointerStoreDisp,
+        /**
+         * Repeat move from {@code x} to {@code y} using {@code z} words.
+         */
+        RepeatMoveWords,
+        /**
+         * Repeat move from {@code x} to {@code y} using {@code z} words.
+         */
+        RepeatMoveBytes,
+        /**
+         * Compare value at at address {@code x} with value in {@code y} and store value {@code z} at address {@code x}
+         * if it was equal to {@code y}.
+         */
+        PointerCAS,
+        /**
+         * Call the {@link JavaMethod} defined by {@code extra}  with {@code args} and put the result in {@code r}.
+         */
+        CallRuntime,
+        /**
+         * Transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
+         */
+        Jmp,
+       /**
+         * If {@code x == y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
+         */
+        Jeq,
+        /**
+         * If {@code x != y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
+         */
+        Jneq,
+        /**
+         * If {@code x > y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
+         */
+        Jgt,
+        /**
+         * If {@code x >= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
+         */
+        Jgteq,
+        /**
+         * If {@code x unsigned >= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
+         */
+        Jugteq,
+        /**
+         * If {@code x < y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
+         */
+        Jlt,
+        /**
+         * If {@code x <= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
+         */
+        Jlteq,
+        /**
+         * Decreases the input by one and jumps to the target if the input is not 0.
+         */
+        DecAndJumpNotZero,
+        /**
+         * If bit designated by {@code z} at effective address defined by base {@code x} and offset {@code y}
+         * is set transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
+         */
+        Jbset,
+        /**
+         * Bind the {@link XirLabel label} identified by {@code extra} to the current instruction and update any references to it.
+         * A label may be bound more than once to the same location.
+         */
+        Bind,
+        /**
+         * Record a safepoint.
+         */
+        Safepoint,
+        /**
+         * Pushes a value onto the stack.
+         */
+        Push,
+        /**
+         * Pops a value from the stack.
+         */
+        Pop,
+        /**
+         * Marks a position in the generated native code.
+         */
+        Mark,
+        /**
+         * Load instruction pointer of the next instruction in a destination register.
+         */
+        Here,
+        /**
+         * Inserts nop instructions, with the given size in bytes.
+         */
+        Nop,
+        /**
+         * This instruction should never be reached, this is useful for debugging purposes.
+         */
+         ShouldNotReachHere
+    }
+
+    public/*private*/ void append(XirInstruction xirInstruction) {
+        assert !finished : "no instructions can be added to finished template";
+        instructions.add(xirInstruction);
+    }
+
+    public XirLabel createInlineLabel(String name) {
+        final XirLabel result = new XirLabel(name, this.labels.size(), true);
+        labels.add(result);
+        return result;
+    }
+
+    public XirLabel createOutOfLineLabel(String name) {
+        final XirLabel result = new XirLabel(name, this.labels.size(), false);
+        labels.add(result);
+        return result;
+    }
+
+    public void mov(XirOperand result, XirOperand a) {
+        append(new XirInstruction(result.kind, Mov, result, a));
+    }
+
+    public void add(XirOperand result, XirOperand a, XirOperand b) {
+        append(new XirInstruction(result.kind, Add, result, a, b));
+    }
+
+    public void sub(XirOperand result, XirOperand a, XirOperand b) {
+        append(new XirInstruction(result.kind, Sub, result, a, b));
+    }
+
+    public void div(XirOperand result, XirOperand a, XirOperand b) {
+        append(new XirInstruction(result.kind, Div, result, a, b));
+    }
+
+    public void mul(XirOperand result, XirOperand a, XirOperand b) {
+        append(new XirInstruction(result.kind, Mul, result, a, b));
+    }
+
+    public void mod(XirOperand result, XirOperand a, XirOperand b) {
+        append(new XirInstruction(result.kind, Mod, result, a, b));
+    }
+
+    public void shl(XirOperand result, XirOperand a, XirOperand b) {
+        append(new XirInstruction(result.kind, Shl, result, a, b));
+    }
+
+    public void shr(XirOperand result, XirOperand a, XirOperand b) {
+        append(new XirInstruction(result.kind, Shr, result, a, b));
+    }
+
+    public void and(XirOperand result, XirOperand a, XirOperand b) {
+        append(new XirInstruction(result.kind, And, result, a, b));
+    }
+
+    public void or(XirOperand result, XirOperand a, XirOperand b) {
+        append(new XirInstruction(result.kind, Or, result, a, b));
+    }
+
+    public void xor(XirOperand result, XirOperand a, XirOperand b) {
+        append(new XirInstruction(result.kind, Xor, result, a, b));
+    }
+
+    public void nullCheck(XirOperand pointer) {
+        append(new XirInstruction(Kind.Object, NullCheck, VOID, pointer));
+    }
+
+    public void pload(Kind kind, XirOperand result, XirOperand pointer, boolean canTrap) {
+        append(new XirInstruction(kind, canTrap, PointerLoad, result, pointer));
+    }
+
+    public void pstore(Kind kind, XirOperand pointer, XirOperand value, boolean canTrap) {
+        append(new XirInstruction(kind, canTrap, PointerStore, null, pointer, value));
+    }
+
+    public void pload(Kind kind, XirOperand result, XirOperand pointer, XirOperand offset, boolean canTrap) {
+        append(new XirInstruction(kind, new AddressAccessInformation(canTrap), PointerLoadDisp, result, pointer, offset));
+    }
+
+    public void pstore(Kind kind, XirOperand pointer, XirOperand offset, XirOperand value, boolean canTrap) {
+        append(new XirInstruction(kind, new AddressAccessInformation(canTrap), PointerStoreDisp, VOID, pointer, offset, value));
+    }
+
+    public void pload(Kind kind, XirOperand result, XirOperand pointer, XirOperand index, int disp, Scale scale,  boolean canTrap) {
+        append(new XirInstruction(kind, new AddressAccessInformation(canTrap, disp, scale), PointerLoadDisp, result, pointer, index));
+    }
+
+    public void lea(XirOperand result, XirOperand pointer, XirOperand index, int disp, Scale scale) {
+        append(new XirInstruction(target.wordKind, new AddressAccessInformation(false, disp, scale), LoadEffectiveAddress, result, pointer, index));
+    }
+
+    public void repmov(XirOperand src, XirOperand dest, XirOperand length) {
+        append(new XirInstruction(target.wordKind, null, RepeatMoveWords, null, src, dest, length));
+    }
+
+    public void here(XirOperand dst) {
+        append(new XirInstruction(target.wordKind, null, Here, dst));
+    }
+
+    public void repmovb(XirOperand src, XirOperand dest, XirOperand length) {
+        append(new XirInstruction(target.wordKind, null, RepeatMoveBytes, null, src, dest, length));
+    }
+
+    public void pstore(Kind kind, XirOperand pointer, XirOperand index, XirOperand value, int disp, Scale scale, boolean canTrap) {
+        append(new XirInstruction(kind, new AddressAccessInformation(canTrap, disp, scale), PointerStoreDisp, VOID, pointer, index, value));
+    }
+
+    public void pcas(Kind kind, XirOperand result, XirOperand pointer, XirOperand newValue, XirOperand oldValue) {
+        append(new XirInstruction(kind, null, PointerCAS, result, pointer, newValue, oldValue));
+    }
+
+    public void jmp(XirLabel l) {
+        append(new XirInstruction(Kind.Void, l, Jmp, null));
+    }
+
+    public void decAndJumpNotZero(XirLabel l, XirOperand val) {
+        append(new XirInstruction(Kind.Void, l, DecAndJumpNotZero, null, val));
+    }
+
+    public void jmpRuntime(Object rt) {
+        append(new XirInstruction(Kind.Void, rt, Jmp, null));
+    }
+
+    public void jeq(XirLabel l, XirOperand a, XirOperand b) {
+        jcc(Jeq, l, a, b);
+    }
+
+    private void jcc(XirOp op, XirLabel l, XirOperand a, XirOperand b) {
+        append(new XirInstruction(Kind.Void, l, op, null, a, b));
+    }
+
+    public void jneq(XirLabel l, XirOperand a, XirOperand b) {
+        jcc(Jneq, l, a, b);
+    }
+
+    public void jgt(XirLabel l, XirOperand a, XirOperand b) {
+        jcc(Jgt, l, a, b);
+    }
+
+    public void jgteq(XirLabel l, XirOperand a, XirOperand b) {
+        jcc(Jgteq, l, a, b);
+    }
+
+    public void jugteq(XirLabel l, XirOperand a, XirOperand b) {
+        jcc(Jugteq, l, a, b);
+    }
+
+    public void jlt(XirLabel l, XirOperand a, XirOperand b) {
+        jcc(Jlt, l, a, b);
+    }
+
+    public void jlteq(XirLabel l, XirOperand a, XirOperand b) {
+        jcc(Jlteq, l, a, b);
+    }
+
+    public void jbset(XirLabel l, XirOperand a, XirOperand b, XirOperand c) {
+        append(new XirInstruction(Kind.Void, l, Jbset, null, a, b, c));
+    }
+
+    public void bindInline(XirLabel l) {
+        assert l.inline;
+        append(new XirInstruction(Kind.Void, l, Bind, null));
+    }
+
+    public void bindOutOfLine(XirLabel l) {
+        assert !l.inline;
+        append(new XirInstruction(Kind.Void, l, Bind, null));
+    }
+
+    public void safepoint() {
+        append(new XirInstruction(Kind.Void, null, Safepoint, null));
+    }
+
+    public void push(XirOperand value) {
+        append(new XirInstruction(Kind.Void, Push, VOID, value));
+    }
+
+    public void pop(XirOperand result) {
+        append(new XirInstruction(result.kind, Pop, result));
+    }
+
+    public XirMark mark(Object id, XirMark... references) {
+        XirMark mark = new XirMark(id, references);
+        marks.add(mark);
+        append(new XirInstruction(Kind.Void, mark, Mark, null));
+        return mark;
+    }
+
+    public void nop(int size) {
+        append(new XirInstruction(Kind.Void, size, Nop, null));
+    }
+
+    public void shouldNotReachHere() {
+        append(new XirInstruction(Kind.Void, null, ShouldNotReachHere, null));
+    }
+
+    public void shouldNotReachHere(String message) {
+        append(new XirInstruction(Kind.Void, message, ShouldNotReachHere, null));
+    }
+
+    public void callRuntime(Object rt, XirOperand result, XirOperand... args) {
+        callRuntime(rt, result, false, args);
+    }
+
+    public void callRuntime(Object rt, XirOperand result, boolean useInfoAfter, XirOperand... args) {
+        Kind resultKind = result == null ? Kind.Void : result.kind;
+        append(new XirInstruction(resultKind, new RuntimeCallInformation(rt, useInfoAfter), CallRuntime, result, args));
+    }
+
+    /**
+     * Terminates the assembly, checking invariants, in particular that {@link #resultOperand} is set, and setting {@link #finished} to {@code true}.
+     */
+    private void end() {
+        assert !finished : "template may only be finished once!";
+        assert resultOperand != null : "result operand should be set";
+        finished = true;
+    }
+
+    /**
+     * Creates an {@link XirVariableParameter variable input parameter}  of given name and {@link Kind kind}.
+     * @param name a name for the parameter
+     * @param kind the parameter kind
+     * @return the  {@link XirVariableParameter}
+     */
+    public XirVariableParameter createInputParameter(String name, Kind kind, boolean canBeConstant) {
+        assert !finished;
+        return new XirVariableParameter(this, name, kind, canBeConstant);
+    }
+
+    public XirVariableParameter createInputParameter(String name, Kind kind) {
+        return createInputParameter(name, kind, false);
+    }
+
+    /**
+     * Creates an {@link XirConstantParameter constant input parameter}  of given name and {@link Kind kind}.
+     * @param name a name for the parameter
+     * @param kind the parameter kind
+     * @return the  {@link XirConstantParameter}
+     */
+    public XirConstantParameter createConstantInputParameter(String name, Kind kind) {
+        assert !finished;
+        return new XirConstantParameter(this, name, kind);
+    }
+
+    public XirConstant createConstant(Constant constant) {
+        assert !finished;
+        XirConstant temp = new XirConstant(this, constant);
+        constants.add(temp);
+        return temp;
+    }
+
+    public XirOperand createTemp(String name, Kind kind) {
+        assert !finished;
+        XirTemp temp = new XirTemp(this, name, kind, true);
+        temps.add(temp);
+        return temp;
+    }
+
+    public XirOperand createRegister(String name, Kind kind, Register register) {
+        return createRegister(name, kind, register, false);
+    }
+
+    public XirOperand createRegisterTemp(String name, Kind kind, Register register) {
+        return createRegister(name, kind, register, true);
+    }
+
+    private XirOperand createRegister(String name, Kind kind, Register register, boolean reserve) {
+        assert !finished;
+        XirRegister fixed = new XirRegister(this, name, register.asValue(kind), reserve);
+        temps.add(fixed);
+        return fixed;
+    }
+
+    public XirParameter getParameter(String name) {
+        for (XirParameter param : parameters) {
+            if (param.name.toString().equals(name)) {
+                return param;
+            }
+        }
+        throw new IllegalArgumentException("no parameter: " + name);
+    }
+
+    public XirTemp getTemp(String name) {
+        for (XirTemp temp : temps) {
+            if (temp.name.toString().equals(name)) {
+                return temp;
+            }
+        }
+        throw new IllegalArgumentException("no temp: " + name);
+    }
+
+    public XirConstant i(int v) {
+        return createConstant(Constant.forInt(v));
+    }
+
+    public XirConstant l(long v) {
+        return createConstant(Constant.forLong(v));
+    }
+
+    public XirConstant b(boolean v) {
+        return createConstant(Constant.forBoolean(v));
+    }
+
+    public XirConstant o(Object obj) {
+        return createConstant(Constant.forObject(obj));
+    }
+
+    public void reserveOutgoingStack(int size) {
+        outgoingStackSize = Math.max(outgoingStackSize, size);
+    }
+
+    /**
+     * Finishes the assembly of a non-stub template, providing the {@link #resultOperand} and constructs the {@link XirTemplate}.
+     * @param result the {@link XirOperand} to be set as the {@link #resultOperand}
+     * @param name the name of the template
+     * @return the generated template
+     */
+    public XirTemplate finishTemplate(XirOperand result, String name) {
+        assert this.resultOperand == null;
+        assert result != null;
+        this.resultOperand = result;
+        final XirTemplate template = buildTemplate(name, false);
+        end();
+        return template;
+    }
+
+    /**
+     * Finishes the assembly of a non-stub template and constructs the {@link XirTemplate}.
+     * @param name the name of the template
+     * @return the generated template
+     */
+    public XirTemplate finishTemplate(String name) {
+        final XirTemplate template = buildTemplate(name, false);
+        end();
+        return template;
+    }
+
+    /**
+     * Finishes the assembly of a {@link XirTemplate.GlobalFlags#GLOBAL_STUB stub} and constructs the {@link XirTemplate}.
+     * @param name the name of the template
+     * @return the generated template
+     */
+    public XirTemplate finishStub(String name) {
+        final XirTemplate template = buildTemplate(name, true);
+        end();
+        return template;
+    }
+
+    /**
+     * Builds the {@link XirTemplate} from the assembly state in this object.
+     * The actual assembly is dependent on the target architecture and implemented
+     * in a concrete subclass.
+     * @param name the name of the template
+     * @param isStub {@code true} if the template represents a {@link XirTemplate.GlobalFlags#GLOBAL_STUB stub}
+     * @return the generated template
+     */
+    protected abstract XirTemplate buildTemplate(String name, boolean isStub);
+
+    public abstract XirAssembler copy();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirGenerator.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009, 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.max.cri.xir;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.JavaType.*;
+
+/**
+ * Represents the interface through which the compiler requests the XIR for a given bytecode from the runtime system.
+ */
+public interface XirGenerator {
+
+    XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, JavaMethod method);
+
+    XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, JavaMethod method, boolean megamorph);
+
+    XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, JavaMethod method);
+
+    XirSnippet genInvokeStatic(XirSite site, JavaMethod method);
+
+    XirSnippet genMonitorEnter(XirSite site, XirArgument receiver, XirArgument lockAddress);
+
+    XirSnippet genMonitorExit(XirSite site, XirArgument receiver, XirArgument lockAddress);
+
+    XirSnippet genNewInstance(XirSite site, JavaType type);
+
+    XirSnippet genNewArray(XirSite site, XirArgument length, Kind elementKind, JavaType componentType, JavaType arrayType);
+
+    XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, JavaType type);
+
+    XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile);
+
+    XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile);
+
+    XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, ResolvedJavaType type, JavaTypeProfile profile);
+
+    /**
+     * Generates code that checks that the {@linkplain Representation#ObjectHub hub} of
+     * an object is identical to a given hub constant. In pseudo code:
+     * <pre>
+     *     if (object.getHub() != hub) {
+     *       jump(falseSuccessor)
+     *     }
+     * </pre>
+     * This snippet should only be used when the object is guaranteed not to be null.
+     */
+    XirSnippet genTypeBranch(XirSite site, XirArgument thisHub, XirArgument otherHub, JavaType type);
+
+    /**
+     * Initializes the XIR generator for the given XIR assembler.
+     *
+     * @param asm the XIR assembler
+     */
+    void initialize(XirAssembler asm);
+
+}
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirSite.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirSite.java	Wed Jul 18 10:50:57 2012 -0700
@@ -25,7 +25,7 @@
 import com.oracle.graal.api.code.*;
 
 /**
- * Encapsulates the notion of a site where XIR can be supplied. It is supplied to the {@link RiXirGenerator} by the
+ * Encapsulates the notion of a site where XIR can be supplied. It is supplied to the {@link XirGenerator} by the
  * compiler for each place where XIR can be generated. This interface allows a number of queries, including the
  * bytecode-level location and optimization hints computed by the compiler.
  */
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirSnippet.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirSnippet.java	Wed Jul 18 10:50:57 2012 -0700
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.CompilationResult.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.max.cri.xir.CiXirAssembler.*;
+import com.oracle.max.cri.xir.XirAssembler.*;
 
 /**
  * Represents a {@link XirTemplate template of XIR} along with the {@link XirArgument arguments} to be passed to the
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirTemplate.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirTemplate.java	Wed Jul 18 10:50:57 2012 -0700
@@ -25,7 +25,7 @@
 import java.io.*;
 import java.util.*;
 
-import com.oracle.max.cri.xir.CiXirAssembler.*;
+import com.oracle.max.cri.xir.XirAssembler.*;
 
 /**
  * Represents a completed template of XIR code that has been first assembled by
@@ -71,12 +71,12 @@
     /**
      * The sequence of instructions for the fast (inline) path.
      */
-    public final CiXirAssembler.XirInstruction[] fastPath;
+    public final XirAssembler.XirInstruction[] fastPath;
 
     /**
      * The sequence of instructions for the slow (out of line) path.
      */
-    public final CiXirAssembler.XirInstruction[] slowPath;
+    public final XirAssembler.XirInstruction[] slowPath;
 
     /**
      * Labels used in control transfers.
@@ -130,8 +130,8 @@
                        int variableCount,
                        boolean allocateResultOperand,
                        XirOperand resultOperand,
-                       CiXirAssembler.XirInstruction[] fastPath,
-                       CiXirAssembler.XirInstruction[] slowPath,
+                       XirAssembler.XirInstruction[] fastPath,
+                       XirAssembler.XirInstruction[] slowPath,
                        XirLabel[] labels,
                        XirParameter[] parameters,
                        XirTemp[] temps,
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/package-info.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/package-info.java	Wed Jul 18 10:50:57 2012 -0700
@@ -24,14 +24,14 @@
  * XIR defines a domain specific instruction set for expressing the lowering of bytecode operations. The details of the
  * lowering operations are entirely encapsulated in the runtime and are provided to the compiler on request using
  * {@link com.oracle.max.cri.xir.XirSnippet XIR snippets}. A snippet is a combination of a {@link com.oracle.max.cri.xir.XirTemplate
- * template}, which is a sequence of {@link com.oracle.max.cri.xir.CiXirAssembler.XirInstruction XIR instructions} that has
- * unbound {@link com.oracle.max.cri.xir.CiXirAssembler.XirParameter parameters}, and site-specific
+ * template}, which is a sequence of {@link com.oracle.max.cri.xir.XirAssembler.XirInstruction XIR instructions} that has
+ * unbound {@link com.oracle.max.cri.xir.XirAssembler.XirParameter parameters}, and site-specific
  * {@link com.oracle.max.cri.xir.XirArgument arguments} that are bound to the parameters.
  * <p>
  * The runtime is responsible for creating the {@link com.oracle.max.cri.xir.XirTemplate templates} and provides these to the
  * compiler as part of the initialization process.
  * <p>
  * The XIR instruction set has no textual representation, and therefore no parser. An assembly is represented by an
- * instance of {@link com.oracle.max.cri.xir.CiXirAssembler}, which provides methods to create instructions and operands.
+ * instance of {@link com.oracle.max.cri.xir.XirAssembler}, which provides methods to create instructions and operands.
  */
 package com.oracle.max.cri.xir;
--- a/graal/overview.html	Thu Jul 05 11:48:30 2012 +0200
+++ b/graal/overview.html	Wed Jul 18 10:50:57 2012 -0700
@@ -30,7 +30,7 @@
 </head>
 <body>
 
-<a href="modules.svg" title="Click to enlarge"><img src="modules.jpg" width="400"/></a>
+<a href="modules.html" title="Click to enlarge"><img src="modules.jpg" width="400"/></a>
 <p>
 This document is the unified Javadoc for the Graal code base.
 The module dependency graph is shown above.
--- a/mx/commands.py	Thu Jul 05 11:48:30 2012 +0200
+++ b/mx/commands.py	Wed Jul 18 10:50:57 2012 -0700
@@ -969,142 +969,18 @@
         mx.abort('jacocoreport takes only one argument : an output directory')
     mx.run_java(['-jar', jacocoreport.get_path(True), '-in', 'jacoco.exec', '-g', join(_graal_home, 'graal'), out])
 
-def _fix_overview_summary(path, topLink):
-    """
-    Processes an "overview-summary.html" generated by javadoc to put the complete
-    summary text above the Packages table.
-    """
-
-    # This uses scraping and so will break if the relevant content produced by javadoc changes in any way!
-    with open(path) as fp:
-        content = fp.read()
-
-    class Chunk:
-        def __init__(self, content, ldelim, rdelim):
-            lindex = content.find(ldelim)
-            rindex = content.find(rdelim)
-            self.ldelim = ldelim
-            self.rdelim = rdelim
-            if lindex != -1 and rindex != -1 and rindex > lindex:
-                self.text = content[lindex + len(ldelim):rindex]
-            else:
-                self.text = None
-
-        def replace(self, content, repl):
-            lindex = content.find(self.ldelim)
-            rindex = content.find(self.rdelim)
-            old = content[lindex:rindex + len(self.rdelim)]
-            return content.replace(old, repl)
-
-    chunk1 = Chunk(content, """<div class="header">
-<div class="subTitle">
-<div class="block">""", """</div>
-</div>
-<p>See: <a href="#overview_description">Description</a></p>
-</div>""")
-
-    chunk2 = Chunk(content, """<div class="footer"><a name="overview_description">
-<!--   -->
-</a>
-<div class="subTitle">
-<div class="block">""", """</div>
-</div>
-</div>
-<!-- ======= START OF BOTTOM NAVBAR ====== -->""")
-
-    assert chunk1.text, 'Could not find header section in ' + path
-    assert chunk2.text, 'Could not find footer section in ' + path
-
-    content = chunk1.replace(content, '<div class="header"><div class="subTitle"><div class="block">' + topLink + chunk2.text +'</div></div></div>')
-    content = chunk2.replace(content, '')
-
-    with open(path, 'w') as fp:
-        fp.write(content)
-
 def site(args):
     """creates a website containing javadoc and the project dependency graph"""
 
-    parser = ArgumentParser(prog='site')
-    parser.add_argument('-d', '--base', action='store', help='directory for generated site', required=True, metavar='<dir>')
-
-    args = parser.parse_args(args)
-
-    args.base = os.path.abspath(args.base)
-    tmpbase = tempfile.mkdtemp(prefix=basename(args.base) + '.', dir=dirname(args.base))
-    unified = join(tmpbase, 'all')
-
-    try:
-        # Create javadoc for each project
-        mx.javadoc(['--base', tmpbase])
-
-        # Create unified javadoc for all projects
-        mx.javadoc(['--base', tmpbase,
-                    '--unified',
-                    '--arg', '@-windowtitle', '--arg', '@Graal OpenJDK Project Documentation',
-                    '--arg', '@-doctitle', '--arg', '@Graal OpenJDK Project Documentation',
-                    '--arg', '@-overview', '--arg', '@' + join(_graal_home, 'graal', 'overview.html')])
-        os.rename(join(tmpbase, 'javadoc'), unified)
-
-        # Generate dependency graph with Graphviz
-        _, tmp = tempfile.mkstemp()
-        try:
-            svg = join(tmpbase, 'all', 'modules.svg')
-            jpg = join(tmpbase, 'all', 'modules.jpg')
-            with open(tmp, 'w') as fp:
-                print >> fp, 'digraph projects {'
-                print >> fp, 'rankdir=BT;'
-                print >> fp, 'size = "13,13";'
-                print >> fp, 'node [shape=rect, fontcolor="blue"];'
-                #print >> fp, 'edge [color="green"];'
-                for p in mx.projects():
-                    print >> fp, '"' + p.name + '" [URL = "../' + p.name + '/javadoc/index.html", target = "_top"]'
-                    for dep in p.canonical_deps():
-                        if mx.project(dep, False):
-                            print >> fp, '"' + p.name + '" -> "' + dep + '"'
-                depths = dict()
-                for p in mx.projects():
-                    d = p.max_depth()
-                    depths.setdefault(d, list()).append(p.name)
-                for d, names in depths.iteritems():
-                    print >> fp, '{ rank = same; "' + '"; "'.join(names) + '"; }'
-                print >> fp, '}'
-
-            mx.run(['dot', '-Tsvg', '-o' + svg, '-Tjpg', '-o' + jpg, tmp])
-
-        finally:
-            os.remove(tmp)
-
-        # Post-process generated SVG to remove title elements which most browsers
-        # render as redundant (and annoying) tooltips.
-        with open(svg, 'r') as fp:
-            content = fp.read()
-        content = re.sub('<title>.*</title>', '', content)
-        content = re.sub('xlink:title="[^"]*"', '', content)
-        with open(svg, 'w') as fp:
-            fp.write(content)
-
-        # Post-process generated overview-summary.html files
-        top = join(tmpbase, 'all', 'overview-summary.html')
-        for root, _, files in os.walk(tmpbase):
-            for f in files:
-                if f == 'overview-summary.html':
-                    path = join(root, f)
-                    topLink = ''
-                    if top != path:
-                        link = os.path.relpath(join(tmpbase, 'all', 'index.html'), dirname(path))
-                        topLink = '<p><a href="' + link + '", target="_top"><b>[return to the overall Graal documentation]</b></a></p>'
-                    _fix_overview_summary(path, topLink)
-
-
-        if exists(args.base):
-            shutil.rmtree(args.base)
-        shutil.move(tmpbase, args.base)
-
-        print 'Created website - root is ' + join(args.base, 'all', 'index.html')
-
-    finally:
-        if exists(tmpbase):
-            shutil.rmtree(tmpbase)
+    return mx.site(['--name', 'Graal',
+                    '--jd', '@-tag', '--jd', '@test:X',
+                    '--jd', '@-tag', '--jd', '@run:X',
+                    '--jd', '@-tag', '--jd', '@bug:X',
+                    '--jd', '@-tag', '--jd', '@summary:X',
+                    '--jd', '@-tag', '--jd', '@vmoption:X',
+                    '--overview', join(_graal_home, 'graal', 'overview.html'),
+                    '--title', 'Graal OpenJDK Project Documentation',
+                    '--dot-output-base', 'modules'] + args)
 
 def mx_init():
     _vmbuild = 'product'
--- a/mxtool/mx.py	Thu Jul 05 11:48:30 2012 +0200
+++ b/mxtool/mx.py	Wed Jul 18 10:50:57 2012 -0700
@@ -57,7 +57,8 @@
 
   env
       A set of environment variable definitions. These override any
-      existing environment variables.
+      existing environment variables. Common properties set here
+      include JAVA_HOME and IGNORED_PROJECTS.
 
 The includes and env files are typically not put under version control
 as they usually contain local file-system paths.
@@ -86,6 +87,13 @@
         If "true" then this library will be omitted from a class path
         if it doesn't exist on the file system and no URLs are specified.
 
+    sourcePath
+        The file system path for a jar file containing the library sources.
+
+    sourceUrls
+        A comma separated list of URLs from which the library source jar can
+        be downloaded and saved in the location specified by 'sourcePath'.
+
 Project specification format:
 
     project@<name>@<prop>=<value>
@@ -194,7 +202,11 @@
                 if includeLibs and not dep in deps:
                     deps.append(dep)
             else:
-                dep = project(name)
+                dep = _projects.get(name, None)
+                if dep is None:
+                    if name in _opts.ignored_projects:
+                        abort('project named ' + name + ' required by ' + self.name + ' is ignored')
+                    abort('dependency named ' + name + ' required by ' + self.name + ' is not found')
                 if not dep in deps:
                     dep.all_deps(deps, includeLibs)
         if not self in deps and includeSelf:
@@ -302,21 +314,33 @@
     
 
 class Library(Dependency):
-    def __init__(self, suite, name, path, mustExist, urls):
+    def __init__(self, suite, name, path, mustExist, urls, sourcePath, sourceUrls):
         Dependency.__init__(self, suite, name)
         self.path = path.replace('/', os.sep)
         self.urls = urls
         self.mustExist = mustExist
+        self.sourcePath = sourcePath
+        self.sourceUrls = sourceUrls
 
     def get_path(self, resolve):
         path = self.path
         if not isabs(path):
             path = join(self.suite.dir, path)
         if resolve and self.mustExist and not exists(path):
-            assert not len(self.urls) == 0, 'cannot find required library  ' + self.name + " " + path;
+            assert not len(self.urls) == 0, 'cannot find required library ' + self.name + ' ' + path;
             print('Downloading ' + self.name + ' from ' + str(self.urls))
             download(path, self.urls)
+        return path
 
+    def get_source_path(self, resolve):
+        path = self.sourcePath
+        if path is None:
+            return None
+        if not isabs(path):
+            path = join(self.suite.dir, path)
+        if resolve and len(self.sourceUrls) != 0 and not exists(path):
+            print('Downloading sources for ' + self.name + ' from ' + str(self.sourceUrls))
+            download(path, self.sourceUrls)
         return path
 
     def append_to_classpath(self, cp, resolve):
@@ -397,7 +421,9 @@
             path = attrs.pop('path')
             mustExist = attrs.pop('optional', 'false') != 'true'
             urls = pop_list(attrs, 'urls')
-            l = Library(self, name, path, mustExist, urls)
+            sourcePath = attrs.pop('sourcePath', None)
+            sourceUrls = pop_list(attrs, 'sourceUrls')
+            l = Library(self, name, path, mustExist, urls, sourcePath, sourceUrls)
             l.__dict__.update(attrs)
             self.libs.append(l)
 
@@ -449,7 +475,8 @@
             existing = _projects.get(p.name)
             if existing is not None:
                 abort('cannot override project  ' + p.name + ' in ' + p.dir + " with project of the same name in  " + existing.dir)
-            _projects[p.name] = p
+            if not p.name in _opts.ignored_projects:
+                _projects[p.name] = p
         for l in self.libs:
             existing = _libs.get(l.name)
             if existing is not None:
@@ -566,6 +593,8 @@
     """
     p = _projects.get(name)
     if p is None and fatalIfMissing:
+        if name in _opts.ignored_projects:
+            abort('project named ' + name + ' is ignored')
         abort('project named ' + name + ' not found')
     return p
 
@@ -671,6 +700,7 @@
         self.add_argument('--Ja', action='append', dest='java_args_sfx', help='suffix Java VM arguments (e.g. --Ja @-dsa)', metavar='@<args>', default=[])
         self.add_argument('--user-home', help='users home directory', metavar='<path>', default=os.path.expanduser('~'))
         self.add_argument('--java-home', help='JDK installation directory (must be JDK 6 or later)', metavar='<path>')
+        self.add_argument('--ignore-project', action='append', dest='ignored_projects', help='name of project to ignore', metavar='<name>', default=[])
         if get_os() != 'windows':
             # Time outs are (currently) implemented with Unix specific functionality
             self.add_argument('--timeout', help='Timeout (in seconds) for command', type=int, default=0, metavar='<secs>')
@@ -703,6 +733,8 @@
         os.environ['JAVA_HOME'] = opts.java_home
         os.environ['HOME'] = opts.user_home
 
+        opts.ignored_projects = opts.ignored_projects + os.environ.get('IGNORED_PROJECTS', '').split(',')
+
         commandAndArgs = opts.__dict__.pop('commandAndArgs')
         return opts, commandAndArgs
 
@@ -1155,6 +1187,7 @@
     parser.add_argument('--no-java', action='store_false', dest='java', help='do not build Java projects')
     parser.add_argument('--no-native', action='store_false', dest='native', help='do not build native projects')
     parser.add_argument('--jdt', help='Eclipse installation or path to ecj.jar for using the Eclipse batch compiler (default: ' + defaultEcjPath + ')', default=defaultEcjPath, metavar='<path>')
+    parser.add_argument('--jdt-warning-as-error', action='store_true', help='convert all Eclipse batch compiler warnings to errors')
 
     if suppliedParser:
         parser.add_argument('remainder', nargs=REMAINDER, metavar='...')
@@ -1194,6 +1227,8 @@
         else:
             if not args.java:
                 continue
+            if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+                continue
 
         # skip building this Java project if its Java compliance level is "higher" than the configured JDK
         if javaCompliance < p.javaCompliance:
@@ -1285,6 +1320,7 @@
         argfile.write('\n'.join(javafilelist))
         argfile.close()
 
+        toBeDeleted = [argfileName]
         try:
             if jdtJar is None:
                 log('Compiling Java sources for {0} with javac...'.format(p.name))
@@ -1305,11 +1341,22 @@
                 if not exists(jdtProperties):
                     log('JDT properties file {0} not found'.format(jdtProperties))
                 else:
-                    jdtArgs += ['-properties', jdtProperties]
+                    # convert all warnings to errors
+                    if args.jdt_warning_as_error:
+                        jdtPropertiesTmp = jdtProperties + '.tmp'
+                        with open(jdtProperties) as fp:
+                            content = fp.read().replace('=warning', '=error')
+                        with open(jdtPropertiesTmp, 'w') as fp:
+                            fp.write(content)
+                        toBeDeleted.append(jdtPropertiesTmp)
+                        jdtArgs += ['-properties', jdtPropertiesTmp]
+                    else:
+                        jdtArgs += ['-properties', jdtProperties]
                 jdtArgs.append('@' + argfile.name)
                 run(jdtArgs)
         finally:
-            os.remove(argfileName)
+            for n in toBeDeleted:
+                os.remove(n)
 
     if suppliedParser:
         return args
@@ -1668,6 +1715,9 @@
         # Every Java program depends on the JRE
         out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.jdt.launching.JRE_CONTAINER'})
 
+        if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+            out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.pde.core.requiredPlugins'})
+
         for dep in p.all_deps([], True):
             if dep == p:
                 continue;
@@ -1681,13 +1731,18 @@
                     path = dep.path
                     if dep.mustExist:
                         dep.get_path(resolve=True)
-                        if isabs(path):
-                            out.element('classpathentry', {'exported' : 'true', 'kind' : 'lib', 'path' : path})
-                        else:
+                        if not isabs(path):
                             # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
                             # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
                             # safest to simply use absolute paths.
-                            out.element('classpathentry', {'exported' : 'true', 'kind' : 'lib', 'path' : join(suite.dir, path)})
+                            path = join(suite.dir, path)
+
+                        attributes = {'exported' : 'true', 'kind' : 'lib', 'path' : path}
+
+                        sourcePath = dep.get_source_path(resolve=True)
+                        if sourcePath is not None:
+                            attributes['sourcepath'] = sourcePath
+                        out.element('classpathentry', attributes)
             else:
                 out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + dep.name})
 
@@ -1742,11 +1797,19 @@
             out.element('name', data='net.sf.eclipsecs.core.CheckstyleBuilder')
             out.element('arguments', data='')
             out.close('buildCommand')
+        if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+            for buildCommand in ['org.eclipse.pde.ManifestBuilder', 'org.eclipse.pde.SchemaBuilder']:
+                out.open('buildCommand')
+                out.element('name', data=buildCommand)
+                out.element('arguments', data='')
+                out.close('buildCommand')
         out.close('buildSpec')
         out.open('natures')
         out.element('nature', data='org.eclipse.jdt.core.javanature')
         if exists(csConfig):
             out.element('nature', data='net.sf.eclipsecs.core.CheckstyleNature')
+        if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+            out.element('nature', data='org.eclipse.pde.PluginNature')
         out.close('natures')
         out.close('projectDescription')
         update_file(join(p.dir, '.project'), out.xml(indent='\t', newl='\n'))
@@ -1781,6 +1844,9 @@
         if p.native:
             continue
 
+        if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project
+            continue
+
         if not exists(join(p.dir, 'nbproject')):
             os.makedirs(join(p.dir, 'nbproject'))
 
@@ -1993,6 +2059,7 @@
     parser.add_argument('--arg', action='append', dest='extra_args', help='extra Javadoc arguments (e.g. --arg @-use)', metavar='@<arg>', default=[])
     parser.add_argument('-m', '--memory', action='store', help='-Xmx value to pass to underlying JVM')
     parser.add_argument('--packages', action='store', help='comma separated packages to process (omit to process all packages)')
+    parser.add_argument('--exclude-packages', action='store', help='comma separated packages to exclude')
 
     args = parser.parse_args(args)
 
@@ -2006,6 +2073,10 @@
     if args.packages is not None:
         packages = [name for name in args.packages.split(',')]
 
+    exclude_packages = []
+    if args.exclude_packages is not None:
+        exclude_packages = [name for name in args.exclude_packages.split(',')]
+
     def outDir(p):
         if args.base is None:
             return join(p.dir, docDir)
@@ -2039,7 +2110,8 @@
                 if len([name for name in files if name.endswith('.java')]) != 0:
                     pkg = root[len(sourceDir) + 1:].replace(os.sep,'.')
                     if len(packages) == 0 or pkg in packages:
-                        pkgs.add(pkg)
+                        if len(exclude_packages) == 0 or not pkg in exclude_packages:
+                            pkgs.add(pkg)
         return pkgs
 
     extraArgs = [a.lstrip('@') for a in args.extra_args]
@@ -2066,26 +2138,33 @@
             cp = classpath(p.name, includeSelf=True)
             sp = os.pathsep.join(p.source_dirs())
             overviewFile = join(p.dir, 'overview.html')
-            overview = []
-            if exists(overviewFile):
-                overview = ['-overview', overviewFile]
+            delOverviewFile = False
+            if not exists(overviewFile):
+                with open(overviewFile, 'w') as fp:
+                    print >> fp, '<html><body>Documentation for the <code>' + p.name + '</code> project.</body></html>'
+                delOverviewFile = True
             nowarnAPI = []
             if not args.warnAPI:
                 nowarnAPI.append('-XDignore.symbol.file')
-            log('Generating {2} for {0} in {1}'.format(p.name, out, docDir))
-            run([java().javadoc, memory,
-                 '-windowtitle', p.name + ' javadoc',
-                 '-XDignore.symbol.file',
-                 '-classpath', cp,
-                 '-quiet',
-                 '-d', out,
-                 '-sourcepath', sp] +
-                 links +
-                 extraArgs +
-                 overview +
-                 nowarnAPI +
-                 list(pkgs))
-            log('Generated {2} for {0} in {1}'.format(p.name, out, docDir))
+            try:
+                log('Generating {2} for {0} in {1}'.format(p.name, out, docDir))
+                run([java().javadoc, memory,
+                     '-windowtitle', p.name + ' javadoc',
+                     '-XDignore.symbol.file',
+                     '-classpath', cp,
+                     '-quiet',
+                     '-d', out,
+                     '-overview', overviewFile,
+                     '-sourcepath', sp] +
+                     links +
+                     extraArgs +
+                     nowarnAPI +
+                     list(pkgs))
+                log('Generated {2} for {0} in {1}'.format(p.name, out, docDir))
+            finally:
+                if delOverviewFile:
+                    os.remove(overviewFile)
+                
     else:
         # The projects must be built to ensure javadoc can find class files for all referenced classes
         build(['--no-native'])
@@ -2119,6 +2198,166 @@
              list(pkgs))
         log('Generated {2} for {0} in {1}'.format(', '.join(names), out, docDir))
 
+def site(args):
+    """creates a website containing javadoc and the project dependency graph"""
+
+    parser = ArgumentParser(prog='site')
+    parser.add_argument('-d', '--base', action='store', help='directory for generated site', required=True, metavar='<dir>')
+    parser.add_argument('--name', action='store', help='name of overall documentation', required=True, metavar='<name>')
+    parser.add_argument('--overview', action='store', help='path to the overview content for overall documentation', required=True, metavar='<path>')
+    parser.add_argument('--projects', action='store', help='comma separated projects to process (omit to process all projects)')
+    parser.add_argument('--jd', action='append', help='extra Javadoc arguments (e.g. --jd @-use)', metavar='@<arg>', default=[])
+    parser.add_argument('--exclude-packages', action='store', help='comma separated packages to exclude', metavar='<pkgs>')
+    parser.add_argument('--dot-output-base', action='store', help='base file name (relative to <dir>/all) for project dependency graph .svg and .jpg files generated by dot (omit to disable dot generation)', metavar='<path>')
+    parser.add_argument('--title', action='store', help='value used for -windowtitle and -doctitle javadoc args for overall documentation (default: "<name>")', metavar='<title>')
+    args = parser.parse_args(args)
+
+    args.base = os.path.abspath(args.base)
+    tmpbase = tempfile.mkdtemp(prefix=basename(args.base) + '.', dir=dirname(args.base))
+    unified = join(tmpbase, 'all')
+
+    exclude_packages_arg = []
+    if args.exclude_packages is not None:
+        exclude_packages_arg = ['--exclude-packages', args.exclude_packages]
+
+    projects = sorted_deps()
+    projects_arg = []
+    if args.projects is not None:
+        projects_arg = ['--projects', args.projects]
+        projects = [project(name) for name in args.projects.split(',')]
+
+    extra_javadoc_args = []
+    for a in args.jd:
+        extra_javadoc_args.append('--arg')
+        extra_javadoc_args.append('@' + a)
+
+    try:
+        # Create javadoc for each project
+        javadoc(['--base', tmpbase] + exclude_packages_arg + projects_arg + extra_javadoc_args)
+
+        # Create unified javadoc for all projects
+        title = args.title if args.title is not None else args.name
+        javadoc(['--base', tmpbase,
+                 '--unified',
+                 '--arg', '@-windowtitle', '--arg', '@' + title,
+                 '--arg', '@-doctitle', '--arg', '@' + title,
+                 '--arg', '@-overview', '--arg', '@' + args.overview] + exclude_packages_arg + projects_arg + extra_javadoc_args)
+        os.rename(join(tmpbase, 'javadoc'), unified)
+
+        # Generate dependency graph with Graphviz
+        if args.dot_output_base is not None:
+            dot = join(tmpbase, 'all', str(args.dot_output_base) + '.dot')
+            svg = join(tmpbase, 'all', str(args.dot_output_base) + '.svg')
+            jpg = join(tmpbase, 'all', str(args.dot_output_base) + '.jpg')
+            html = join(tmpbase, 'all', str(args.dot_output_base) + '.html')
+            with open(dot, 'w') as fp:
+                dim = len(projects)
+                print >> fp, 'digraph projects {'
+                print >> fp, 'rankdir=BT;'
+                print >> fp, 'size = "' + str(dim) + ',' + str(dim) + '";'
+                print >> fp, 'node [shape=rect, fontcolor="blue"];'
+                #print >> fp, 'edge [color="green"];'
+                for p in projects:
+                    print >> fp, '"' + p.name + '" [URL = "../' + p.name + '/javadoc/index.html", target = "_top"]'
+                    for dep in p.canonical_deps():
+                        if dep in [proj.name for proj in projects]:
+                            print >> fp, '"' + p.name + '" -> "' + dep + '"'
+                depths = dict()
+                for p in projects:
+                    d = p.max_depth()
+                    depths.setdefault(d, list()).append(p.name)
+                print >> fp, '}'
+
+            run(['dot', '-Tsvg', '-o' + svg, '-Tjpg', '-o' + jpg, dot])
+
+        # Post-process generated SVG to remove title elements which most browsers
+        # render as redundant (and annoying) tooltips.
+        with open(svg, 'r') as fp:
+            content = fp.read()
+        content = re.sub('<title>.*</title>', '', content)
+        content = re.sub('xlink:title="[^"]*"', '', content)
+        with open(svg, 'w') as fp:
+            fp.write(content)
+
+        # Create HTML that embeds the svg file in an <object> frame
+        with open(html, 'w') as fp:
+            print >> fp, '<html><body><object data="modules.svg" type="image/svg+xml"></object></body></html>'
+
+        # Post-process generated overview-summary.html files
+        def fix_overview_summary(path, topLink):
+            """
+            Processes an "overview-summary.html" generated by javadoc to put the complete
+            summary text above the Packages table.
+            """
+        
+            # This uses scraping and so will break if the relevant content produced by javadoc changes in any way!
+            with open(path) as fp:
+                content = fp.read()
+        
+            class Chunk:
+                def __init__(self, content, ldelim, rdelim):
+                    lindex = content.find(ldelim)
+                    rindex = content.find(rdelim)
+                    self.ldelim = ldelim
+                    self.rdelim = rdelim
+                    if lindex != -1 and rindex != -1 and rindex > lindex:
+                        self.text = content[lindex + len(ldelim):rindex]
+                    else:
+                        self.text = None
+        
+                def replace(self, content, repl):
+                    lindex = content.find(self.ldelim)
+                    rindex = content.find(self.rdelim)
+                    old = content[lindex:rindex + len(self.rdelim)]
+                    return content.replace(old, repl)
+        
+            chunk1 = Chunk(content, """<div class="header">
+<div class="subTitle">
+<div class="block">""", """</div>
+</div>
+<p>See: <a href="#overview_description">Description</a></p>
+</div>""")
+        
+            chunk2 = Chunk(content, """<div class="footer"><a name="overview_description">
+<!--   -->
+</a>
+<div class="subTitle">
+<div class="block">""", """</div>
+</div>
+</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->""")
+        
+            assert chunk1.text, 'Could not find header section in ' + path
+            assert chunk2.text, 'Could not find footer section in ' + path
+        
+            content = chunk1.replace(content, '<div class="header"><div class="subTitle"><div class="block">' + topLink + chunk2.text +'</div></div></div>')
+            content = chunk2.replace(content, '')
+        
+            with open(path, 'w') as fp:
+                fp.write(content)
+        
+        top = join(tmpbase, 'all', 'overview-summary.html')
+        for root, _, files in os.walk(tmpbase):
+            for f in files:
+                if f == 'overview-summary.html':
+                    path = join(root, f)
+                    topLink = ''
+                    if top != path:
+                        link = os.path.relpath(join(tmpbase, 'all', 'index.html'), dirname(path))
+                        topLink = '<p><a href="' + link + '", target="_top"><b>[return to the overall ' + args.name + ' documentation]</b></a></p>'
+                    fix_overview_summary(path, topLink)
+
+
+        if exists(args.base):
+            shutil.rmtree(args.base)
+        shutil.move(tmpbase, args.base)
+
+        print 'Created website - root is ' + join(args.base, 'all', 'index.html')
+
+    finally:
+        if exists(tmpbase):
+            shutil.rmtree(tmpbase)
+
 def findclass(args):
     """find all classes matching a given substring"""
 
@@ -2181,6 +2420,7 @@
     'projectgraph': [projectgraph, ''],
     'javap': [javap, ''],
     'javadoc': [javadoc, '[options]'],
+    'site': [site, '[options]'],
     'netbeansinit': [netbeansinit, ''],
     'projects': [show_projects, ''],
 }
@@ -2226,7 +2466,13 @@
     command_args = commandAndArgs[1:]
 
     if not commands.has_key(command):
-        abort('mx: unknown command \'{0}\'\n{1}use "mx help" for more options'.format(command, _format_commands()))
+        hits = [c for c in commands.iterkeys() if c.startswith(command)]
+        if len(hits) == 1:
+            command = hits[0]
+        elif len(hits) == 0:
+            abort('mx: unknown command \'{0}\'\n{1}use "mx help" for more options'.format(command, _format_commands()))
+        else:
+            abort('mx: command \'{0}\' is ambiguous\n    {1}'.format(command, ' '.join(hits)))
 
     c, _ = commands[command][:2]
     def term_handler(signum, frame):
--- a/src/cpu/x86/vm/nativeInst_x86.hpp	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/cpu/x86/vm/nativeInst_x86.hpp	Wed Jul 18 10:50:57 2012 -0700
@@ -186,21 +186,17 @@
  public:
   enum Intel_specific_constants {
     instruction_code            = 0xFF,
-    instruction_size            =    2,
     instruction_offset          =    0,
-    return_address_offset       =    2
+    return_address_offset_norex =    2,
+    return_address_offset_rex   =    3
   };
 
-  address instruction_address() const       { return addr_at(instruction_offset); }
-  address next_instruction_address() const  { return addr_at(return_address_offset); }
-
-
-  static bool is_call_reg_at(address instr) {
-    return ((*instr) & 0xFF) == NativeCallReg::instruction_code;
-  }
-
-  static bool is_call_reg_before(address return_address) {
-    return is_call_reg_at(return_address - NativeCallReg::return_address_offset);
+  int next_instruction_offset() const  {
+    if (ubyte_at(0) == NativeCallReg::instruction_code) {
+      return return_address_offset_norex;
+    } else {
+      return return_address_offset_rex;
+    }
   }
 };
 
@@ -555,7 +551,9 @@
 
 inline bool NativeInstruction::is_illegal()      { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; }
 inline bool NativeInstruction::is_call()         { return ubyte_at(0) == NativeCall::instruction_code; }
-inline bool NativeInstruction::is_call_reg()     { return ubyte_at(0) == NativeCallReg::instruction_code; }
+inline bool NativeInstruction::is_call_reg()     { return ubyte_at(0) == NativeCallReg::instruction_code ||
+                                                          (ubyte_at(1) == NativeCallReg::instruction_code &&
+                                                           (ubyte_at(0) == Assembler::REX || ubyte_at(0) == Assembler::REX_B)); }
 inline bool NativeInstruction::is_return()       { return ubyte_at(0) == NativeReturn::instruction_code ||
                                                           ubyte_at(0) == NativeReturnX::instruction_code; }
 inline bool NativeInstruction::is_jump()         { return ubyte_at(0) == NativeJump::instruction_code ||
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java	Wed Jul 18 10:50:57 2012 -0700
@@ -61,6 +61,7 @@
     private GraphDocument document;
     private FolderNode root;
     private Server server;
+    private Server binaryServer;
 
     private OutlineTopComponent() {
         initComponents();
@@ -111,11 +112,14 @@
 
             @Override
             public void started(Group g) {
-                getDocument().addElement(g);
+                synchronized(OutlineTopComponent.this) {
+                    getDocument().addElement(g);
+                }
             }
         };
         
-        server = new Server(callback);
+        server = new Server(callback, false);
+        binaryServer = new Server(callback, true);
     }
 
     public void clear() {
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/ImportAction.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/ImportAction.java	Wed Jul 18 10:50:57 2012 -0700
@@ -26,15 +26,18 @@
 
 import com.sun.hotspot.igv.coordinator.OutlineTopComponent;
 import com.sun.hotspot.igv.data.GraphDocument;
+import com.sun.hotspot.igv.data.serialization.BinaryParser;
+import com.sun.hotspot.igv.data.serialization.GraphParser;
+import com.sun.hotspot.igv.data.serialization.ParseMonitor;
 import com.sun.hotspot.igv.data.serialization.Parser;
-import com.sun.hotspot.igv.data.serialization.XMLParser;
 import com.sun.hotspot.igv.settings.Settings;
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.nio.channels.FileChannel;
+import java.nio.file.StandardOpenOption;
 import javax.swing.Action;
 import javax.swing.JFileChooser;
 import javax.swing.KeyStroke;
@@ -42,32 +45,30 @@
 import javax.swing.filechooser.FileFilter;
 import org.netbeans.api.progress.ProgressHandle;
 import org.netbeans.api.progress.ProgressHandleFactory;
-import org.openide.DialogDisplayer;
-import org.openide.NotifyDescriptor;
+import org.openide.util.Exceptions;
 import org.openide.util.HelpCtx;
 import org.openide.util.NbBundle;
 import org.openide.util.RequestProcessor;
 import org.openide.util.actions.CallableSystemAction;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
 public final class ImportAction extends CallableSystemAction {
+    private static final int WORKUNITS = 10000;
 
     public static FileFilter getFileFilter() {
         return new FileFilter() {
 
             @Override
             public boolean accept(File f) {
-                return f.getName().toLowerCase().endsWith(".xml") || f.isDirectory();
+                return f.getName().toLowerCase().endsWith(".xml") || f.getName().toLowerCase().endsWith(".bgv") || f.isDirectory();
             }
 
             @Override
             public String getDescription() {
-                return "XML files (*.xml)";
+                return "Graph files (*.xml, *.bgv)";
             }
         };
     }
@@ -88,71 +89,59 @@
             }
 
             Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath());
-
             try {
-                final FileInputStream inputStream = new FileInputStream(file);
-                final InputSource is = new InputSource(inputStream);
-
+                final FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ);
                 final ProgressHandle handle = ProgressHandleFactory.createHandle("Opening file " + file.getName());
-                final int basis = 1000;
-                handle.start(basis);
-                final int start = inputStream.available();
-
-                final XMLParser.ParseMonitor parseMonitor = new XMLParser.ParseMonitor() {
-
+                handle.start(WORKUNITS);
+                final long start = channel.size();
+                ParseMonitor monitor = new ParseMonitor() {
                     @Override
-                    public void setProgress(double d) {
+                    public void updateProgress() {
                         try {
-                            int curAvailable = inputStream.available();
-                            int prog = (int) (basis * (double) (start - curAvailable) / (double) start);
+                            int prog = (int) (WORKUNITS * (double) channel.position() / (double) start);
                             handle.progress(prog);
                         } catch (IOException ex) {
                         }
                     }
-
                     @Override
                     public void setState(String state) {
-                        setProgress(0.0);
+                        updateProgress();
                         handle.progress(state);
                     }
                 };
-                final Parser parser = new Parser();
+                final GraphParser parser;
+                if (file.getName().endsWith(".xml")) {
+                    parser = new Parser(channel, monitor, null);
+                } else if (file.getName().endsWith(".bgv")) {
+                    parser = new BinaryParser(channel, monitor, null);
+                } else {
+                    parser = null;
+                }
                 final OutlineTopComponent component = OutlineTopComponent.findInstance();
-
-                component.requestActive();
-
                 RequestProcessor.getDefault().post(new Runnable() {
-
                     @Override
                     public void run() {
                         try {
-                            final GraphDocument document = parser.parse(is, parseMonitor);
-                            parseMonitor.setState("Finishing");
-                            SwingUtilities.invokeLater(new Runnable(){
-
-                                @Override
-                                public void run() {
-                                    component.getDocument().addGraphDocument(document);
-                                }
-                            });
-                        } catch (SAXException ex) {
-                            String s = "Exception during parsing the XML file, could not load document!";
-                            if (ex instanceof XMLParser.MissingAttributeException) {
-                                XMLParser.MissingAttributeException e = (XMLParser.MissingAttributeException) ex;
-                                s += "\nMissing attribute \"" + e.getAttributeName() + "\"";
+                            final GraphDocument document = parser.parse();
+                            if (document != null) {
+                                SwingUtilities.invokeLater(new Runnable(){
+                                    @Override
+                                    public void run() {
+                                        component.requestActive();
+                                        component.getDocument().addGraphDocument(document);
+                                    }
+                                });
                             }
-                            ex.printStackTrace();
-                            NotifyDescriptor d = new NotifyDescriptor.Message(s, NotifyDescriptor.ERROR_MESSAGE);
-                            DialogDisplayer.getDefault().notify(d);
+                        } catch (IOException ex) {
+                            Exceptions.printStackTrace(ex);
                         }
                         handle.finish();
                     }
                 });
-
             } catch (FileNotFoundException ex) {
-                ex.printStackTrace();
+                Exceptions.printStackTrace(ex);
             } catch (IOException ex) {
-                ex.printStackTrace();
+                Exceptions.printStackTrace(ex);
             }
         }
     }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java	Wed Jul 18 10:50:57 2012 -0700
@@ -243,10 +243,7 @@
     }
 
     public void addEdge(InputEdge c) {
-        // Be tolerant with duplicated edges.
-        if (!edges.contains(c)) {
-            edges.add(c);
-        }
+        edges.add(c);
     }
 
     public Group getGroup() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,772 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.sun.hotspot.igv.data.serialization;
+
+import com.sun.hotspot.igv.data.*;
+import com.sun.hotspot.igv.data.Properties;
+import com.sun.hotspot.igv.data.services.GroupCallback;
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.swing.SwingUtilities;
+
+public class BinaryParser implements GraphParser {
+    private static final int BEGIN_GROUP = 0x00;
+    private static final int BEGIN_GRAPH = 0x01;
+    private static final int CLOSE_GROUP = 0x02;
+
+    private static final int POOL_NEW = 0x00;
+    private static final int POOL_STRING = 0x01;
+    private static final int POOL_ENUM = 0x02;
+    private static final int POOL_CLASS = 0x03;
+    private static final int POOL_METHOD = 0x04;
+    private static final int POOL_NULL = 0x05;
+    private static final int POOL_NODE_CLASS = 0x06;
+    private static final int POOL_FIELD = 0x07;
+    private static final int POOL_SIGNATURE = 0x08;
+    
+    private static final int KLASS = 0x00;
+    private static final int ENUM_KLASS = 0x01;
+    
+    private static final int PROPERTY_POOL = 0x00;
+    private static final int PROPERTY_INT = 0x01;
+    private static final int PROPERTY_LONG = 0x02;
+    private static final int PROPERTY_DOUBLE = 0x03;
+    private static final int PROPERTY_FLOAT = 0x04;
+    private static final int PROPERTY_TRUE = 0x05;
+    private static final int PROPERTY_FALSE = 0x06;
+    private static final int PROPERTY_ARRAY = 0x07;
+    
+    private static final String NO_BLOCK = "noBlock";
+    
+    private final GroupCallback callback;
+    private final List<Object> constantPool;
+    private final ByteBuffer buffer;
+    private final ReadableByteChannel channel;
+    private final Deque<Folder> folderStack;
+    private final ParseMonitor monitor;
+    
+    private enum Length {
+        S,
+        M,
+        L
+    }
+    
+    private interface LengthToString {
+        String toString(Length l);
+    }
+    
+    private static abstract class Member implements LengthToString {
+        public final Klass holder;
+        public final int accessFlags;
+        public final String name;
+        public Member(Klass holder, String name, int accessFlags) {
+            this.holder = holder;
+            this.accessFlags = accessFlags;
+            this.name = name;
+        }
+    }
+    
+    private static class Method extends Member {
+        public final Signature signature;
+        public final byte[] code;
+        public Method(String name, Signature signature, byte[] code, Klass holder, int accessFlags) {
+            super(holder, name, accessFlags);
+            this.signature = signature;
+            this.code = code;
+        }
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append(holder).append('.').append(name).append('(');
+            for (int i = 0; i < signature.argTypes.length; i++) {
+                if (i > 0) {
+                    sb.append(", ");
+                }
+                sb.append(signature.argTypes[i]);
+            }
+            sb.append(')');
+            return sb.toString();
+        }
+        @Override
+        public String toString(Length l) {
+            switch(l) {
+                case M:
+                    return holder.toString(Length.L) + "." + name;
+                case S:
+                    return holder.toString(Length.S) + "." + name;
+                default:
+                case L:
+                    return toString();
+            }
+        }
+    }
+    
+    private static class Signature {
+        public final String returnType;
+        public final String[] argTypes;
+        public Signature(String returnType, String[] argTypes) {
+            this.returnType = returnType;
+            this.argTypes = argTypes;
+        }
+    }
+    
+    private static class Field extends Member {
+        public final String type;
+        public Field(String type, Klass holder, String name, int accessFlags) {
+            super(holder, name, accessFlags);
+            this.type = type;
+        }
+        @Override
+        public String toString() {
+            return holder + "." + name;
+        }
+        @Override
+        public String toString(Length l) {
+            switch(l) {
+                case M:
+                    return holder.toString(Length.L) + "." + name;
+                case S:
+                    return holder.toString(Length.S) + "." + name;
+                default:
+                case L:
+                    return toString();
+            }
+        }
+    }
+    
+    private static class Klass implements LengthToString {
+        public final String name;
+        public final String simpleName;
+        public Klass(String name) {
+            this.name = name;
+            String simple;
+            try {
+                simple = name.substring(name.lastIndexOf('.') + 1);
+            } catch (IndexOutOfBoundsException ioobe) {
+                simple = name;
+            }
+            this.simpleName = simple;
+        }
+        @Override
+        public String toString() {
+            return name;
+        }
+        @Override
+        public String toString(Length l) {
+            switch(l) {
+                case S:
+                    return simpleName;
+                default:
+                case L:
+                case M:
+                    return toString();
+            }
+        }
+    }
+    
+    private static class EnumKlass extends Klass {
+        public final String[] values;
+        public EnumKlass(String name, String[] values) {
+            super(name);
+            this.values = values;
+        }
+    }
+    
+    private static class NodeClass {
+        public final String className;
+        public final String nameTemplate;
+        public final List<String> inputs;
+        public final List<String> sux;
+        private NodeClass(String className, String nameTemplate, List<String> inputs, List<String> sux) {
+            this.className = className;
+            this.nameTemplate = nameTemplate;
+            this.inputs = inputs;
+            this.sux = sux;
+        }
+        @Override
+        public String toString() {
+            return className;
+        }
+    }
+    
+    private static class EnumValue implements LengthToString {
+        public EnumKlass enumKlass;
+        public int ordinal;
+        public EnumValue(EnumKlass enumKlass, int ordinal) {
+            this.enumKlass = enumKlass;
+            this.ordinal = ordinal;
+        }
+        @Override
+        public String toString() {
+            return enumKlass.simpleName + "." + enumKlass.values[ordinal];
+        }
+        @Override
+        public String toString(Length l) {
+            switch(l) {
+                case S:
+                    return enumKlass.values[ordinal];
+                default:
+                case M:
+                case L:
+                    return toString();
+            }
+        }
+    }
+
+    public BinaryParser(ReadableByteChannel channel, ParseMonitor monitor, GroupCallback callback) {
+        this.callback = callback;
+        constantPool = new ArrayList<>();
+        buffer = ByteBuffer.allocateDirect(256 * 1024);
+        buffer.flip();
+        this.channel = channel;
+        folderStack = new LinkedList<>();
+        this.monitor = monitor;
+    }
+    
+    private void fill() throws IOException {
+        buffer.compact();
+        if (channel.read(buffer) < 0) {
+            throw new EOFException();
+        }
+        buffer.flip();
+    }
+    
+    private void ensureAvailable(int i) throws IOException {
+        while (buffer.remaining() < i) {
+            fill();
+        }
+    }
+    
+    private int readByte() throws IOException {
+        ensureAvailable(1);
+        return ((int)buffer.get()) & 0xff;
+    }
+
+    private int readInt() throws IOException {
+        ensureAvailable(4);
+        return buffer.getInt();
+    }
+    
+    private char readShort() throws IOException {
+        ensureAvailable(2);
+        return buffer.getChar();
+    }
+    
+    private long readLong() throws IOException {
+        ensureAvailable(8);
+        return buffer.getLong();
+    }
+    
+    private double readDouble() throws IOException {
+        ensureAvailable(8);
+        return buffer.getDouble();
+    }
+    
+    private float readFloat() throws IOException {
+        ensureAvailable(4);
+        return buffer.getFloat();
+    }
+
+    private String readString() throws IOException {
+        int len = readInt();
+        ensureAvailable(len * 2);
+        char[] chars = new char[len];
+        for (int i = 0; i < len; i++) {
+            chars[i] = buffer.getChar();
+        }
+        return new String(chars);
+    }
+
+    private byte[] readBytes() throws IOException {
+        int len = readInt();
+        if (len < 0) {
+            return null;
+        }
+        ensureAvailable(len);
+        byte[] data = new byte[len];
+        buffer.get(data);
+        return data;
+    }
+    
+    private String readIntsToString() throws IOException {
+        int len = readInt();
+        if (len < 0) {
+            return "null";
+        }
+        ensureAvailable(len * 4);
+        StringBuilder sb = new StringBuilder().append('[');
+        for (int i = 0; i < len; i++) {
+            sb.append(buffer.getInt());
+            if (i < len - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+    
+    private String readDoublesToString() throws IOException {
+        int len = readInt();
+        if (len < 0) {
+            return "null";
+        }
+        ensureAvailable(len * 8);
+        StringBuilder sb = new StringBuilder().append('[');
+        for (int i = 0; i < len; i++) {
+            sb.append(buffer.getDouble());
+            if (i < len - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+    
+    private String readPoolObjectsToString() throws IOException {
+        int len = readInt();
+        if (len < 0) {
+            return "null";
+        }
+        StringBuilder sb = new StringBuilder().append('[');
+        for (int i = 0; i < len; i++) {
+            sb.append(readPoolObject(Object.class));
+            if (i < len - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+    
+    private <T> T readPoolObject(Class<T> klass) throws IOException {
+        int type = readByte();
+        if (type == POOL_NULL) {
+            return null;
+        }
+        if (type == POOL_NEW) {
+            return (T) addPoolEntry(klass);
+        }
+        assert assertObjectType(klass, type);
+        int index = readInt();
+        if (index < 0 || index >= constantPool.size()) {
+            throw new IOException("Invalid constant pool index : " + index);
+        }
+        Object obj = constantPool.get(index);
+        return (T) obj;
+    }
+    
+    private boolean assertObjectType(Class<?> klass, int type) {
+        switch(type) {
+            case POOL_CLASS:
+                return klass.isAssignableFrom(EnumKlass.class);
+            case POOL_ENUM:
+                return klass.isAssignableFrom(EnumValue.class);
+            case POOL_METHOD:
+                return klass.isAssignableFrom(Method.class);
+            case POOL_STRING:
+                return klass.isAssignableFrom(String.class);
+            case POOL_NODE_CLASS:
+                return klass.isAssignableFrom(NodeClass.class);
+            case POOL_FIELD:
+                return klass.isAssignableFrom(Field.class);
+            case POOL_SIGNATURE:
+                return klass.isAssignableFrom(Signature.class);
+            case POOL_NULL:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private Object addPoolEntry(Class<?> klass) throws IOException {
+        int index = readInt();
+        int type = readByte();
+        assert assertObjectType(klass, type) : "Wrong object type : " + klass + " != " + type;
+        Object obj;
+        switch(type) {
+            case POOL_CLASS: {
+                String name = readString();
+                int klasstype = readByte();
+                if (klasstype == ENUM_KLASS) {
+                    int len = readInt();
+                    String[] values = new String[len];
+                    for (int i = 0; i < len; i++) {
+                        values[i] = readPoolObject(String.class);
+                    }
+                    obj = new EnumKlass(name, values);
+                } else if (klasstype == KLASS) {
+                    obj = new Klass(name);
+                } else {
+                    throw new IOException("unknown klass type : " + klasstype);
+                }
+                break;
+            }
+            case POOL_ENUM: {
+                EnumKlass enumClass = readPoolObject(EnumKlass.class);
+                int ordinal = readInt();
+                obj = new EnumValue(enumClass, ordinal);
+                break;
+            }
+            case POOL_NODE_CLASS: {
+                String className = readString();
+                String nameTemplate = readString();
+                int inputCount = readShort();
+                List<String> inputs = new ArrayList<>(inputCount);
+                for (int i = 0; i < inputCount; i++) {
+                    inputs.add(readPoolObject(String.class));
+                }
+                int suxCount = readShort();
+                List<String> sux = new ArrayList<>(suxCount);
+                for (int i = 0; i < suxCount; i++) {
+                    sux.add(readPoolObject(String.class));
+                }
+                obj = new NodeClass(className, nameTemplate, inputs, sux);
+                break;
+            }
+            case POOL_METHOD: {
+                Klass holder = readPoolObject(Klass.class);
+                String name = readPoolObject(String.class);
+                Signature sign = readPoolObject(Signature.class);
+                int flags = readInt();
+                byte[] code = readBytes();
+                obj = new Method(name, sign, code, holder, flags);
+                break;
+            }
+            case POOL_FIELD: {
+                Klass holder = readPoolObject(Klass.class);
+                String name = readPoolObject(String.class);
+                String fType = readPoolObject(String.class);
+                int flags = readInt();
+                obj = new Field(fType, holder, name, flags);
+                break;
+            }
+            case POOL_SIGNATURE: {
+                int argc = readShort();
+                String[] args = new String[argc];
+                for (int i = 0; i < argc; i++) {
+                    args[i] = readPoolObject(String.class);
+                }
+                String returnType = readPoolObject(String.class);
+                obj = new Signature(returnType, args);
+                break;
+            }
+            case POOL_STRING: {
+                obj = readString();
+                break;
+            }
+            default:
+                throw new IOException("unknown pool type");
+        }
+        while (constantPool.size() <= index) {
+            constantPool.add(null);
+        }
+        constantPool.set(index, obj);
+        return obj;
+    }
+    
+    private Object readPropertyObject() throws IOException {
+        int type = readByte();
+        switch (type) {
+            case PROPERTY_INT:
+                return readInt();
+            case PROPERTY_LONG:
+                return readLong();
+            case PROPERTY_FLOAT:
+                return readFloat();
+            case PROPERTY_DOUBLE:
+                return readDouble();
+            case PROPERTY_TRUE:
+                return Boolean.TRUE;
+            case PROPERTY_FALSE:
+                return Boolean.FALSE;
+            case PROPERTY_POOL:
+                return readPoolObject(Object.class);
+            case PROPERTY_ARRAY:
+                int subType = readByte();
+                switch(subType) {
+                    case PROPERTY_INT:
+                        return readIntsToString();
+                    case PROPERTY_DOUBLE:
+                        return readDoublesToString();
+                    case PROPERTY_POOL:
+                        return readPoolObjectsToString();
+                    default:
+                        throw new IOException("Unknown type");
+                }
+            default:
+                throw new IOException("Unknown type");
+        }
+    }
+
+    public GraphDocument parse() throws IOException {
+        GraphDocument doc = new GraphDocument();
+        folderStack.push(doc);
+        if (monitor != null) {
+            monitor.setState("Starting parsing");
+        }
+        try {
+            while(true) {
+                parseRoot();
+            }
+        } catch (EOFException e) {
+            
+        }
+        if (monitor != null) {
+            monitor.setState("Finished parsing");
+        }
+        return doc;
+    }
+
+    private void parseRoot() throws IOException {
+        int type = readByte();
+        switch(type) {
+            case BEGIN_GRAPH: {
+                final Folder parent = folderStack.peek();
+                final InputGraph graph = parseGraph();
+                SwingUtilities.invokeLater(new Runnable(){
+                    @Override
+                    public void run() {
+                        parent.addElement(graph);
+                    }
+                });
+                break;
+            }
+            case BEGIN_GROUP: {
+                final Folder parent = folderStack.peek();
+                final Group group = parseGroup(parent);
+                if (callback == null || parent instanceof Group) {
+                    SwingUtilities.invokeLater(new Runnable(){
+                        @Override
+                        public void run() {
+                            parent.addElement(group);
+                        }
+                    });
+                }
+                folderStack.push(group);
+                if (callback != null && parent instanceof GraphDocument) {
+                    callback.started(group);
+                }
+                break;
+            }
+            case CLOSE_GROUP: {
+                if (folderStack.isEmpty()) {
+                    throw new IOException("Unbalanced groups");
+                }
+                folderStack.pop();
+                break;
+            }
+            default:
+                throw new IOException("unknown root : " + type);
+        }
+    }
+
+    private Group parseGroup(Folder parent) throws IOException {
+        String name = readPoolObject(String.class);
+        String shortName = readPoolObject(String.class);
+        if (monitor != null) {
+            monitor.setState(shortName);
+        }
+        Method method = readPoolObject(Method.class);
+        int bci = readInt();
+        Group group = new Group(parent);
+        group.getProperties().setProperty("name", name);
+        if (method != null) {
+            InputMethod inMethod = new InputMethod(group, method.name, shortName, bci);
+            inMethod.setBytecodes("TODO");
+            group.setMethod(inMethod);
+        }
+        return group;
+    }
+    
+    private InputGraph parseGraph() throws IOException {
+        if (monitor != null) {
+            monitor.updateProgress();
+        }
+        String title = readPoolObject(String.class);
+        InputGraph graph = new InputGraph(title);
+        parseNodes(graph);
+        parseBlocks(graph);
+        graph.ensureNodesInBlocks();
+        return graph;
+    }
+    
+    private void parseBlocks(InputGraph graph) throws IOException {
+        int blockCount = readInt();
+        List<Edge> edges = new LinkedList<>();
+        for (int i = 0; i < blockCount; i++) {
+            int id = readInt();
+            String name = id >= 0 ? Integer.toString(id) : NO_BLOCK;
+            InputBlock block = graph.addBlock(name);
+            int nodeCount = readInt();
+            for (int j = 0; j < nodeCount; j++) {
+                int nodeId = readInt();
+                block.addNode(nodeId);
+                graph.getNode(nodeId).getProperties().setProperty("block", name);
+            }
+            int edgeCount = readInt();
+            for (int j = 0; j < edgeCount; j++) {
+                int to = readInt();
+                edges.add(new Edge(id, to));
+            }
+        }
+        for (Edge e : edges) {
+            String fromName = e.from >= 0 ? Integer.toString(e.from) : NO_BLOCK;
+            String toName = e.to >= 0 ? Integer.toString(e.to) : NO_BLOCK;
+            graph.addBlockEdge(graph.getBlock(fromName), graph.getBlock(toName));
+        }
+    }
+
+    private void parseNodes(InputGraph graph) throws IOException {
+        int count = readInt();
+        Map<String, Object> props = new HashMap<>();
+        List<Edge> edges = new LinkedList<>();
+        for (int i = 0; i < count; i++) {
+            int id = readInt();
+            InputNode node = new InputNode(id);
+            final Properties properties = node.getProperties();
+            NodeClass nodeClass = readPoolObject(NodeClass.class);
+            int preds = readByte();
+            if (preds > 0) {
+                properties.setProperty("hasPredecessor", "true");
+            }
+            int propCount = readShort();
+            for (int j = 0; j < propCount; j++) {
+                String key = readPoolObject(String.class);
+                Object value = readPropertyObject();
+                properties.setProperty(key, value != null ? value.toString() : "null");
+                props.put(key, value);
+            }
+            int edgesStart = edges.size();
+            int suxCount = readShort();
+            for (int j = 0; j < suxCount; j++) {
+                int sux = readInt();
+                int index = readShort();
+                edges.add(new Edge(id, sux, (char) j, nodeClass.sux.get(index), false));
+            }
+            int inputCount = readShort();
+            for (int j = 0; j < inputCount; j++) {
+                int in = readInt();
+                int index = readShort();
+                edges.add(new Edge(in, id, (char) (preds + j), nodeClass.inputs.get(index), true));
+            }
+            properties.setProperty("name", createName(edges.subList(edgesStart, edges.size()), props, nodeClass.nameTemplate));
+            properties.setProperty("class", nodeClass.className);
+            switch (nodeClass.className) {
+                case "BeginNode":
+                    properties.setProperty("shortName", "B");
+                    break;
+                case "EndNode":
+                    properties.setProperty("shortName", "E");
+                    break;
+            }
+            graph.addNode(node);
+            props.clear();
+        }
+        for (Edge e : edges) {
+            char fromIndex = e.input ? 1 : e.num;
+            char toIndex = e.input ? e.num : 0;
+            graph.addEdge(new InputEdge(fromIndex, toIndex, e.from, e.to, e.label));
+        }
+    }
+    
+    private String createName(List<Edge> edges, Map<String, Object> properties, String template) {
+        Pattern p = Pattern.compile("\\{(p|i)#([a-zA-Z0-9$_]+)(/(l|m|s))?\\}");
+        Matcher m = p.matcher(template);
+        StringBuffer sb = new StringBuffer();
+        while (m.find()) {
+            String name = m.group(2);
+            String type = m.group(1);
+            String result;
+            switch (type) {
+                case "i":
+                    StringBuilder inputString = new StringBuilder();
+                    for(Edge edge : edges) {
+                        if (name.equals(edge.label)) {
+                            if (inputString.length() > 0) {
+                                inputString.append(", ");
+                            }
+                            inputString.append(edge.from);
+                        }
+                    }
+                    result = inputString.toString();
+                    break;
+                case "p":
+                    Object prop = properties.get(name);
+                    String length = m.group(4);
+                    if (prop == null) {
+                        result = "?";
+                    } else if (length != null && prop instanceof LengthToString) {
+                        LengthToString lengthProp = (LengthToString) prop;
+                        switch(length) {
+                            default:
+                            case "l":
+                                result = lengthProp.toString(Length.L);
+                                break;
+                            case "m":
+                                result = lengthProp.toString(Length.M);
+                                break;
+                            case "s":
+                                result = lengthProp.toString(Length.S);
+                                break;
+                        }
+                    } else {
+                        result = prop.toString();
+                    }
+                    break;
+                default:
+                    result = "#?#";
+                    break;
+            }
+            result = result.replace("\\", "\\\\");
+            result = result.replace("$", "\\$");
+            m.appendReplacement(sb, result);
+        }
+        m.appendTail(sb);
+        return sb.toString();
+    }
+    
+    private static class Edge {
+        final int from;
+        final int to;
+        final char num;
+        final String label;
+        final boolean input;
+        public Edge(int from, int to) {
+            this(from, to, (char) 0, null, false);
+        }
+        public Edge(int from, int to, char num, String label, boolean input) {
+            this.from = from;
+            this.to = to;
+            this.label = label;
+            this.num = num;
+            this.input = input;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/GraphParser.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,32 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.sun.hotspot.igv.data.serialization;
+
+import com.sun.hotspot.igv.data.GraphDocument;
+import java.io.IOException;
+
+public interface GraphParser {
+    public GraphDocument parse() throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/ParseMonitor.java	Wed Jul 18 10:50:57 2012 -0700
@@ -0,0 +1,33 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.sun.hotspot.igv.data.serialization;
+
+public interface ParseMonitor {
+
+    public void updateProgress();
+
+    public void setState(String state);
+    
+}
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java	Wed Jul 18 10:50:57 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -26,11 +26,12 @@
 import com.sun.hotspot.igv.data.*;
 import com.sun.hotspot.igv.data.serialization.XMLParser.ElementHandler;
 import com.sun.hotspot.igv.data.serialization.XMLParser.HandoverElementHandler;
-import com.sun.hotspot.igv.data.serialization.XMLParser.ParseMonitor;
 import com.sun.hotspot.igv.data.serialization.XMLParser.TopElementHandler;
 import com.sun.hotspot.igv.data.services.GroupCallback;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
@@ -42,13 +43,14 @@
 import javax.xml.validation.SchemaFactory;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
 import org.xml.sax.XMLReader;
 
 /**
  *
  * @author Thomas Wuerthinger
  */
-public class Parser {
+public class Parser implements GraphParser {
 
     public static final String INDENT = "  ";
     public static final String TOP_ELEMENT = "graphDocument";
@@ -99,6 +101,8 @@
     private ArrayList<Pair<String, String>> blockConnections = new ArrayList<>();
     private int maxId = 0;
     private GraphDocument graphDocument;
+    private final ParseMonitor monitor;
+    private final ReadableByteChannel channel;
 
     private int lookupID(String i) {
         try {
@@ -217,6 +221,10 @@
                     }
                 }
             }
+            ParseMonitor monitor = getMonitor();
+            if (monitor != null) {
+                monitor.updateProgress();
+            }
             return curGraph;
         }
 
@@ -460,13 +468,15 @@
         }
     };
 
-    public Parser() {
-        this(null);
+    public Parser(ReadableByteChannel channel) {
+        this(channel, null, null);
     }
 
-    public Parser(GroupCallback groupCallback) {
+    public Parser(ReadableByteChannel channel, ParseMonitor monitor, GroupCallback groupCallback) {
 
         this.groupCallback = groupCallback;
+        this.monitor = monitor;
+        this.channel = channel;
 
         // Initialize dependencies
         xmlDocument.addChild(topHandler);
@@ -510,16 +520,23 @@
     }
 
     // Returns a new GraphDocument object deserialized from an XML input source.
-    public GraphDocument parse(InputSource source, XMLParser.ParseMonitor monitor) throws SAXException {
-        XMLReader reader = createReader();
-
-        reader.setContentHandler(new XMLParser(xmlDocument, monitor));
+    @Override
+    public GraphDocument parse() throws IOException {
+        if (monitor != null) {
+            monitor.setState("Starting parsing");
+        }
         try {
-            reader.parse(source);
-        } catch (IOException ex) {
-            throw new SAXException(ex);
+            XMLReader reader = createReader();
+            reader.setContentHandler(new XMLParser(xmlDocument, monitor));
+            reader.parse(new InputSource(Channels.newInputStream(channel)));
+        } catch (SAXException ex) {
+            if (!(ex instanceof SAXParseException) || !"XML document structures must start and end within the same entity.".equals(ex.getMessage())) {
+                throw new IOException(ex);
+            }
         }
-
+        if (monitor != null) {
+            monitor.setState("Finished parsing");
+        }
         return graphDocument;
     }
 
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java	Wed Jul 18 10:50:57 2012 -0700
@@ -37,13 +37,6 @@
  */
 public class XMLParser implements ContentHandler {
 
-    public static interface ParseMonitor {
-
-        public void setProgress(double d);
-
-        public void setState(String state);
-    }
-
     public static class MissingAttributeException extends SAXException {
 
         private String name;
@@ -197,9 +190,7 @@
 
     @Override
     public void setDocumentLocator(Locator locator) {
-        if (monitor != null) {
-            monitor.setState("Starting parsing");
-        }
+        
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/graphdocument.xsd	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/graphdocument.xsd	Wed Jul 18 10:50:57 2012 -0700
@@ -15,7 +15,10 @@
             <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" />
             <xsd:element name="assembly" type="assemblyType" minOccurs="0" maxOccurs="1" />
             <xsd:element name="method" type="methodType" minOccurs="0" maxOccurs="1" />
-            <xsd:element name="graph" type="graphType" minOccurs="0" maxOccurs="unbounded" />
+            <xsd:choice minOccurs="0" maxOccurs="unbounded" >
+                <xsd:element name="graph" type="graphType" />
+                <xsd:element name="group" type="groupType" />
+            </xsd:choice>
         </xsd:sequence>
         <xsd:attribute name="difference" use="optional" />
     </xsd:complexType>
--- a/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/serialization/ParserTest.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Data/test/unit/src/com/sun/hotspot/igv/data/serialization/ParserTest.java	Wed Jul 18 10:50:57 2012 -0700
@@ -26,11 +26,12 @@
 package com.sun.hotspot.igv.data.serialization;
 
 import com.sun.hotspot.igv.data.*;
-import java.io.CharArrayWriter;
-import java.io.StringReader;
+import java.io.*;
+import java.nio.channels.Channels;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import org.junit.*;
+import org.openide.util.Exceptions;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 
@@ -67,16 +68,17 @@
     }
 
     private void test(GraphDocument document, String xmlString) {
-        
-        StringReader sr = new StringReader(xmlString);
-        InputSource is = new InputSource(sr);
-
         try {
-            Parser parser = new Parser();
-            final GraphDocument parsedDocument = parser.parse(is, null);
-            Util.assertGraphDocumentEquals(document, parsedDocument);
-        } catch (SAXException ex) {
-            fail(ex.toString());
+            InputStream in = new ByteArrayInputStream(xmlString.getBytes("UTF-8"));
+            try {
+                Parser parser = new Parser(Channels.newChannel(in));
+                final GraphDocument parsedDocument = parser.parse();
+                Util.assertGraphDocumentEquals(document, parsedDocument);
+            } catch (SAXException ex) {
+                fail(ex.toString());
+            }
+        } catch (UnsupportedEncodingException ex) {
+            Exceptions.printStackTrace(ex);
         }
     }
 
--- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java	Wed Jul 18 10:50:57 2012 -0700
@@ -58,8 +58,8 @@
         for (Figure f : figures) {
             Properties p = f.getProperties();
             int predCount;
-            if (p.get("predecessorCount") != null) {
-                predCount = Integer.parseInt(p.get("predecessorCount"));
+            if (Boolean.parseBoolean(p.get("hasPredecessor"))) {
+                predCount = 1;
             } else {
                 predCount = 0;
             }
--- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter	Wed Jul 18 10:50:57 2012 -0700
@@ -9,4 +9,7 @@
 colorize("name", "Comp .*", yellow);
 colorize("name", "Virtual.*", green);
 
-colorize("notInOwnBlock", "true", red);
\ No newline at end of file
+colorize("name", "ValuePhi.*|ValueProxy", magenta);
+colorize("name", "Const.*", new java.awt.Color(0.7, 0.7, 0.7));
+colorize("name", "Local.*", new java.awt.Color(0.85, 0.85, 0.85));
+colorize("stamp", "Condition", yellow);
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/noframestate.filter	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/noframestate.filter	Wed Jul 18 10:50:57 2012 -0700
@@ -1,1 +1,2 @@
-remove("class", "FrameState");
\ No newline at end of file
+remove("class", "FrameState");
+remove("class", "Virtual.*");
\ No newline at end of file
--- a/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Client.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Client.java	Wed Jul 18 10:50:57 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -24,42 +24,34 @@
  */
 package com.sun.hotspot.igv.connection;
 
+import com.sun.hotspot.igv.data.serialization.BinaryParser;
 import com.sun.hotspot.igv.data.serialization.Parser;
 import com.sun.hotspot.igv.data.services.GroupCallback;
-import java.io.BufferedInputStream;
 import java.io.IOException;
-import java.io.InputStream;
-import java.net.Socket;
+import java.nio.channels.SocketChannel;
 import org.openide.util.Exceptions;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
 
-/**
- *
- * @author Thomas Wuerthinger
- */
 public class Client implements Runnable {
+    private final boolean binary;
+    private final SocketChannel socket;
+    private final GroupCallback callback;
 
-    private Socket socket;
-    private GroupCallback callback;
-
-    public Client(Socket socket, GroupCallback callback) {
+    public Client(SocketChannel socket, GroupCallback callback, boolean  binary) {
         this.callback = callback;
         this.socket = socket;
+        this.binary = binary;
     }
 
     @Override
     public void run() {
 
         try {
-            InputStream inputStream = new BufferedInputStream(socket.getInputStream());
-            InputSource is = new InputSource(inputStream);
-
-            try {
-                Parser parser = new Parser(callback);
-                parser.parse(is, null);
-            } catch (SAXException ex) {
-                ex.printStackTrace();
+            final SocketChannel channel = socket;
+            channel.configureBlocking(true);
+            if (binary) {
+                new BinaryParser(channel, null, callback).parse();
+            } else {
+                new Parser(channel, null, callback).parse();
             }
         } catch (IOException ex) {
             Exceptions.printStackTrace(ex);
--- a/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Server.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/NetworkConnection/src/com/sun/hotspot/igv/connection/Server.java	Wed Jul 18 10:50:57 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -27,8 +27,9 @@
 import com.sun.hotspot.igv.data.services.GroupCallback;
 import com.sun.hotspot.igv.settings.Settings;
 import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.Socket;
+import java.net.InetSocketAddress;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
 import java.util.prefs.PreferenceChangeEvent;
 import java.util.prefs.PreferenceChangeListener;
 import org.openide.DialogDisplayer;
@@ -40,14 +41,14 @@
  * @author Thomas Wuerthinger
  */
 public class Server implements PreferenceChangeListener {
-
-    private ServerSocket serverSocket;
-    private GroupCallback callback;
+    private final boolean binary;
+    private ServerSocketChannel serverSocket;
+    private final GroupCallback callback;
     private int port;
     private Runnable serverRunnable;
 
-    public Server(GroupCallback callback) {
-
+    public Server(GroupCallback callback, boolean binary) {
+        this.binary = binary;
         this.callback = callback;
         initializeNetwork();
         Settings.get().addPreferenceChangeListener(this);
@@ -56,7 +57,7 @@
     @Override
     public void preferenceChange(PreferenceChangeEvent e) {
 
-        int curPort = Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT));
+        int curPort = Integer.parseInt(Settings.get().get(binary ? Settings.PORT_BINARY : Settings.PORT, binary ? Settings.PORT_BINARY_DEFAULT : Settings.PORT_DEFAULT));
         if (curPort != port) {
             initializeNetwork();
         }
@@ -64,12 +65,13 @@
 
     private void initializeNetwork() {
 
-        int curPort = Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT));
+        int curPort = Integer.parseInt(Settings.get().get(binary ? Settings.PORT_BINARY : Settings.PORT, binary ? Settings.PORT_BINARY_DEFAULT : Settings.PORT_DEFAULT));
         this.port = curPort;
         try {
-            serverSocket = new java.net.ServerSocket(curPort);
+            serverSocket = ServerSocketChannel.open();
+            serverSocket.bind(new InetSocketAddress(curPort));
         } catch (IOException ex) {
-            NotifyDescriptor message = new NotifyDescriptor.Message("Could not create server. Listening for incoming data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
+            NotifyDescriptor message = new NotifyDescriptor.Message("Could not create server. Listening for incoming binary data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
             DialogDisplayer.getDefault().notifyLater(message);
             return;
         }
@@ -80,15 +82,15 @@
             public void run() {
                 while (true) {
                     try {
-                        Socket clientSocket = serverSocket.accept();
+                        SocketChannel clientSocket = serverSocket.accept();
                         if (serverRunnable != this) {
                             clientSocket.close();
                             return;
                         }
-                        RequestProcessor.getDefault().post(new Client(clientSocket, callback), 0, Thread.MAX_PRIORITY);
+                        RequestProcessor.getDefault().post(new Client(clientSocket, callback, binary), 0, Thread.MAX_PRIORITY);
                     } catch (IOException ex) {
                         serverSocket = null;
-                        NotifyDescriptor message = new NotifyDescriptor.Message("Error during listening for incoming connections. Listening for incoming data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
+                        NotifyDescriptor message = new NotifyDescriptor.Message("Error during listening for incoming connections. Listening for incoming binary data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
                         DialogDisplayer.getDefault().notifyLater(message);
                         return;
                     }
--- a/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/Settings.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Settings/src/com/sun/hotspot/igv/settings/Settings.java	Wed Jul 18 10:50:57 2012 -0700
@@ -37,7 +37,9 @@
     public final static String NODE_WIDTH = "nodeWidth";
     public final static String NODE_WIDTH_DEFAULT = "100";
     public final static String PORT = "port";
+    public final static String PORT_BINARY = "portBinary";
     public final static String PORT_DEFAULT = "4444";
+    public final static String PORT_BINARY_DEFAULT = "4445";
     public final static String DIRECTORY = "directory";
     public final static String DIRECTORY_DEFAULT = System.getProperty("user.dir");
 
--- a/src/share/vm/c1/c1_Runtime1.cpp	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Wed Jul 18 10:50:57 2012 -0700
@@ -535,8 +535,9 @@
     if (TraceExceptions) {
       ttyLocker ttyl;
       ResourceMark rm;
-      tty->print_cr("Exception <%s> (0x%x) thrown in compiled method <%s> at PC " PTR_FORMAT " for thread 0x%x",
-                    exception->print_value_string(), (address)exception(), nm->method()->print_value_string(), pc, thread);
+      int offset = pc - nm->code_begin();
+      tty->print_cr("Exception <%s> (0x%x) thrown in compiled method <%s> at PC " PTR_FORMAT " [" PTR_FORMAT "+%d] for thread 0x%x",
+                    exception->print_value_string(), (address)exception(), nm->method()->print_value_string(), pc, nm->code_begin(), offset, thread);
     }
     // for AbortVMOnException flag
     NOT_PRODUCT(Exceptions::debug_check_abort(exception));
--- a/src/share/vm/classfile/systemDictionary.hpp	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Wed Jul 18 10:50:57 2012 -0700
@@ -186,13 +186,12 @@
   template(Short_klass,                  java_lang_Short,                Pre) \
   template(Integer_klass,                java_lang_Integer,              Pre) \
   template(Long_klass,                   java_lang_Long,                 Pre) \
-                                                                                                                     \
-  /* Support for Graal */                                                                                            \
+                                                                                                                      \
+  /* Support for Graal */                                                                                             \
   template(GraalBitMap_klass,                     java_util_BitSet,                                             Opt) \
-  /* graal.hotspot */                                                                                                \
+  /* graal.hotspot */                                                                                                 \
   template(HotSpotKlassOop_klass,                 com_oracle_graal_hotspot_HotSpotKlassOop,                     Opt) \
-  template(HotSpotProxy_klass,                    com_oracle_graal_hotspot_HotSpotProxy,                        Opt) \
-  template(HotSpotTargetMethod_klass,             com_oracle_graal_hotspot_HotSpotTargetMethod,                 Opt) \
+  template(HotSpotCompilationResult_klass,        com_oracle_graal_hotspot_HotSpotCompilationResult,            Opt) \
   template(HotSpotCodeInfo_klass,                 com_oracle_graal_hotspot_meta_HotSpotCodeInfo,                Opt) \
   template(HotSpotCompiledMethod_klass,           com_oracle_graal_hotspot_meta_HotSpotCompiledMethod,          Opt) \
   template(HotSpotJavaType_klass,                 com_oracle_graal_hotspot_meta_HotSpotJavaType,                Opt) \
@@ -200,7 +199,7 @@
   template(HotSpotResolvedJavaField_klass,        com_oracle_graal_hotspot_meta_HotSpotResolvedJavaField,       Opt) \
   template(HotSpotResolvedJavaMethod_klass,       com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethod,      Opt) \
   template(HotSpotResolvedJavaType_klass,         com_oracle_graal_hotspot_meta_HotSpotResolvedJavaType,        Opt) \
-  /* graal.api.code */                                                                                               \
+  /* graal.api.code */                                                                                                \
   template(Assumptions_klass,                     com_oracle_graal_api_code_Assumptions,                        Opt) \
   template(Assumptions_ConcreteMethod_klass,      com_oracle_graal_api_code_Assumptions_ConcreteMethod,         Opt) \
   template(Assumptions_ConcreteSubtype_klass,     com_oracle_graal_api_code_Assumptions_ConcreteSubtype,        Opt) \
@@ -221,7 +220,7 @@
   template(RuntimeCall_klass,                     com_oracle_graal_api_code_RuntimeCall,                        Opt) \
   template(StackSlot_klass,                       com_oracle_graal_api_code_StackSlot,                          Opt) \
   template(VirtualObject_klass,                   com_oracle_graal_api_code_VirtualObject,                      Opt) \
-  /* graal.api.meta */                                                                                               \
+  /* graal.api.meta */                                                                                                \
   template(Constant_klass,                        com_oracle_graal_api_meta_Constant,                           Opt) \
   template(ExceptionHandler_klass,                com_oracle_graal_api_meta_ExceptionHandler,                   Opt) \
   template(Kind_klass,                            com_oracle_graal_api_meta_Kind,                               Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 18 10:50:57 2012 -0700
@@ -267,15 +267,14 @@
   NOT_LP64(  do_alias(intptr_signature,               int_signature)  )                           \
   LP64_ONLY( do_alias(intptr_signature,               long_signature) )                           \
   template(selectAlternative_signature, "(ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;") \
-                                                                                                                                      \
-  /* Support for Graal */                                                                                                             \
-  template(java_util_BitSet,	                                       "java/util/BitSet")                                              \
-  /* graal.hotspot */                                                                                                                 \
+                                                                                                                                       \
+  /* Support for Graal */                                                                                                              \
+  template(java_util_BitSet,	                                       "java/util/BitSet")                                               \
+  /* graal.hotspot */                                                                                                                  \
   template(com_oracle_graal_hotspot_HotSpotGraalRuntime,             "com/oracle/graal/hotspot/HotSpotGraalRuntime")                  \
   template(com_oracle_graal_hotspot_HotSpotKlassOop,                 "com/oracle/graal/hotspot/HotSpotKlassOop")                      \
   template(com_oracle_graal_hotspot_HotSpotOptions,                  "com/oracle/graal/hotspot/HotSpotOptions")                       \
-  template(com_oracle_graal_hotspot_HotSpotProxy,                    "com/oracle/graal/hotspot/HotSpotProxy")                         \
-  template(com_oracle_graal_hotspot_HotSpotTargetMethod,             "com/oracle/graal/hotspot/HotSpotTargetMethod")                  \
+  template(com_oracle_graal_hotspot_HotSpotCompilationResult,        "com/oracle/graal/hotspot/HotSpotCompilationResult")             \
   template(com_oracle_graal_hotspot_bridge_VMToCompiler,             "com/oracle/graal/hotspot/bridge/VMToCompiler")                  \
   template(com_oracle_graal_hotspot_meta_HotSpotCodeInfo,            "com/oracle/graal/hotspot/meta/HotSpotCodeInfo")                 \
   template(com_oracle_graal_hotspot_meta_HotSpotCompiledMethod,      "com/oracle/graal/hotspot/meta/HotSpotCompiledMethod")           \
@@ -284,7 +283,7 @@
   template(com_oracle_graal_hotspot_meta_HotSpotResolvedJavaField,   "com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField")        \
   template(com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethod,  "com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod")       \
   template(com_oracle_graal_hotspot_meta_HotSpotResolvedJavaType,    "com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType")         \
-  /* graal.api.meta */                                                                                                                \
+  /* graal.api.meta */                                                                                                                 \
   template(com_oracle_graal_api_meta_Constant,                       "com/oracle/graal/api/meta/Constant")                            \
   template(com_oracle_graal_api_meta_ConstantPool,                   "com/oracle/graal/api/meta/ConstantPool")                        \
   template(com_oracle_graal_api_meta_ExceptionHandler,               "com/oracle/graal/api/meta/ExceptionHandler")                    \
@@ -293,7 +292,7 @@
   template(com_oracle_graal_api_meta_Kind,                           "com/oracle/graal/api/meta/Kind")                                \
   template(com_oracle_graal_api_meta_ResolvedJavaField,              "com/oracle/graal/api/meta/ResolvedJavaField")                   \
   template(com_oracle_graal_api_meta_Value,                          "com/oracle/graal/api/meta/Value")                               \
-  /* graal.api.code */                                                                                                                \
+  /* graal.api.code */                                                                                                                 \
   template(com_oracle_graal_api_code_Assumptions,                    "com/oracle/graal/api/code/Assumptions")                         \
   template(com_oracle_graal_api_code_Assumptions_MethodContents,     "com/oracle/graal/api/code/Assumptions$MethodContents")          \
   template(com_oracle_graal_api_code_Assumptions_ConcreteSubtype,    "com/oracle/graal/api/code/Assumptions$ConcreteSubtype")         \
--- a/src/share/vm/code/nmethod.cpp	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/vm/code/nmethod.cpp	Wed Jul 18 10:50:57 2012 -0700
@@ -2599,9 +2599,9 @@
 void nmethod::print_nmethod_labels(outputStream* stream, address block_begin) {
   if (block_begin == entry_point())             stream->print_cr("[Entry Point]");
   if (block_begin == verified_entry_point())    stream->print_cr("[Verified Entry Point]");
-  if (block_begin == exception_begin())         stream->print_cr("[Exception Handler]");
+  if (GRAAL_ONLY(_exception_offset >= 0 &&) block_begin == exception_begin())         stream->print_cr("[Exception Handler]");
   if (block_begin == stub_begin())              stream->print_cr("[Stub Code]");
-  if (block_begin == deopt_handler_begin())     stream->print_cr("[Deopt Handler Code]");
+  if (GRAAL_ONLY(_deoptimize_offset >= 0 &&) block_begin == deopt_handler_begin())     stream->print_cr("[Deopt Handler Code]");
 
   if (has_method_handle_invokes())
     if (block_begin == deopt_mh_handler_begin())  stream->print_cr("[Deopt MH Handler Code]");
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Wed Jul 18 10:50:57 2012 -0700
@@ -250,7 +250,7 @@
   _env->set_oop_recorder(_oop_recorder);
   _env->set_dependencies(_dependencies);
   _dependencies = new Dependencies(_env);
-  Handle assumptions_handle = InstalledCode::assumptions(HotSpotTargetMethod::targetMethod(target_method));
+  Handle assumptions_handle = InstalledCode::assumptions(HotSpotCompilationResult::comp(target_method));
   if (!assumptions_handle.is_null()) {
     objArrayHandle assumptions(Thread::current(), (objArrayOop)Assumptions::list(assumptions_handle()));
     int length = assumptions->length();
@@ -273,22 +273,22 @@
 }
 
 // constructor used to create a method
-CodeInstaller::CodeInstaller(Handle& target_method, nmethod*& nm, bool install_code) {
+CodeInstaller::CodeInstaller(Handle& comp_result, nmethod*& nm, bool install_code) {
   _env = CURRENT_ENV;
   GraalCompiler::initialize_buffer_blob();
   CodeBuffer buffer(JavaThread::current()->get_buffer_blob());
-  jobject target_method_obj = JNIHandles::make_local(target_method());
-  initialize_assumptions(JNIHandles::resolve(target_method_obj));
+  jobject comp_result_obj = JNIHandles::make_local(comp_result());
+  initialize_assumptions(JNIHandles::resolve(comp_result_obj));
 
   {
     No_Safepoint_Verifier no_safepoint;
-    initialize_fields(JNIHandles::resolve(target_method_obj));
+    initialize_fields(JNIHandles::resolve(comp_result_obj));
     initialize_buffer(buffer);
     process_exception_handlers();
   }
 
   int stack_slots = _total_frame_size / HeapWordSize; // conversion to words
-  methodHandle method = getMethodFromHotSpotMethod(HotSpotTargetMethod::method(JNIHandles::resolve(target_method_obj))); 
+  methodHandle method = getMethodFromHotSpotMethod(HotSpotCompilationResult::method(JNIHandles::resolve(comp_result_obj))); 
 
   nm = GraalEnv::register_method(method, -1, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
     &_implicit_exception_table, GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, true, false, install_code);
@@ -317,22 +317,23 @@
   id = VmIds::addStub(blob->code_begin());
 }
 
-void CodeInstaller::initialize_fields(oop target_method) {
-  _citarget_method = HotSpotTargetMethod::targetMethod(target_method);
-  _hotspot_method = HotSpotTargetMethod::method(target_method);
+void CodeInstaller::initialize_fields(oop comp_result) {
+  _comp_result = HotSpotCompilationResult::comp(comp_result);
+  _hotspot_method = HotSpotCompilationResult::method(comp_result);
   if (_hotspot_method != NULL) {
-    _parameter_count = getMethodFromHotSpotMethod(_hotspot_method)->size_of_parameters();
+    methodOop method = getMethodFromHotSpotMethod(_hotspot_method);
+    _parameter_count = method->size_of_parameters();
+    TRACE_graal_1("installing code for %s", method->name_and_sig_as_C_string());
   }
-  _name = HotSpotTargetMethod::name(target_method);
-  _sites = (arrayOop) HotSpotTargetMethod::sites(target_method);
-  _exception_handlers = (arrayOop) HotSpotTargetMethod::exceptionHandlers(target_method);
+  _name = HotSpotCompilationResult::name(comp_result);
+  _sites = (arrayOop) HotSpotCompilationResult::sites(comp_result);
+  _exception_handlers = (arrayOop) HotSpotCompilationResult::exceptionHandlers(comp_result);
 
-  _code = (arrayOop) InstalledCode::targetCode(_citarget_method);
-  _code_size = InstalledCode::targetCodeSize(_citarget_method);
+  _code = (arrayOop) InstalledCode::targetCode(_comp_result);
+  _code_size = InstalledCode::targetCodeSize(_comp_result);
   // The frame size we get from the target method does not include the return address, so add one word for it here.
-  _total_frame_size = InstalledCode::frameSize(_citarget_method) + HeapWordSize;
-  _custom_stack_area_offset = InstalledCode::customStackAreaOffset(_citarget_method);
-
+  _total_frame_size = InstalledCode::frameSize(_comp_result) + HeapWordSize;
+  _custom_stack_area_offset = InstalledCode::customStackAreaOffset(_comp_result);
 
   // (very) conservative estimate: each site needs a constant section entry
   _constants_size = _sites->length() * (BytesPerLong*2);
@@ -627,11 +628,12 @@
     assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte");
     next_pc_offset += 3; /* prefix byte + opcode byte + modrm byte */
   } else if (inst->is_call_reg()) {
-    // the inlined vtable stub contains a "call register" instruction, which isn't recognized here
+    // the inlined vtable stub contains a "call register" instruction
     assert(hotspot_method != NULL, "only valid for virtual calls");
     is_call_reg = true;
-    next_pc_offset = pc_offset + NativeCallReg::instruction_size;
+    next_pc_offset = pc_offset + ((NativeCallReg *) inst)->next_instruction_offset();
   } else {
+    tty->print_cr("at pc_offset %d", pc_offset);
     runtime_call->print();
     fatal("unsupported type of instruction for call site");
   }
@@ -695,10 +697,10 @@
 
     TRACE_graal_3("method call");
     switch (_next_call_type) {
+      case MARK_INLINE_INVOKEVIRTUAL: {
+        break;
+      }
       case MARK_INVOKEVIRTUAL:
-        if (is_call_reg) {
-          break;
-        }
       case MARK_INVOKEINTERFACE: {
         assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
 
@@ -787,9 +789,6 @@
         TRACE_graal_3("relocating (HotSpotJavaType) at %016x/%016x", instruction, operand);
       } else {
         jobject value = JNIHandles::make_local(obj());
-        if (obj() == HotSpotProxy::DUMMY_CONSTANT_OBJ()) {
-          value = (jobject) Universe::non_oop_word();
-        }
         *((jobject*) operand) = value;
         _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
         TRACE_graal_3("relocating (oop constant) at %016x/%016x", instruction, operand);
@@ -836,11 +835,20 @@
         _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
         break;
       }
+      case MARK_INVOKEVIRTUAL:
+      case MARK_INVOKEINTERFACE: {
+        // Convert the initial value of the klassOop slot in an inline cache
+        // from NULL to Universe::non_oop_word().
+        NativeMovConstReg* n_copy = nativeMovConstReg_at(instruction);
+        assert(n_copy->data() == 0, "inline cache klassOop initial value should be NULL");
+        n_copy->set_data((intptr_t)Universe::non_oop_word());
+        // Add relocation record for the klassOop embedded in the inline cache
+        _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+      }
+      case MARK_INLINE_INVOKEVIRTUAL:
       case MARK_INVOKE_INVALID:
-      case MARK_INVOKEINTERFACE:
+      case MARK_INVOKESPECIAL:
       case MARK_INVOKESTATIC:
-      case MARK_INVOKESPECIAL:
-      case MARK_INVOKEVIRTUAL:
         _next_call_type = (MarkId) id;
         _invoke_mark_pc = instruction;
         break;
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Wed Jul 18 10:50:57 2012 -0700
@@ -43,6 +43,7 @@
     MARK_INVOKESTATIC               = 0x2002,
     MARK_INVOKESPECIAL              = 0x2003,
     MARK_INVOKEVIRTUAL              = 0x2004,
+    MARK_INLINE_INVOKEVIRTUAL       = 0x2005,
     MARK_IMPLICIT_NULL              = 0x3000,
     MARK_POLL_NEAR                  = 0x3001,
     MARK_POLL_RETURN_NEAR           = 0x3002,
@@ -55,7 +56,7 @@
 
   ciEnv*        _env;
 
-  oop           _citarget_method;
+  oop           _comp_result;
   oop           _hotspot_method;
   oop           _name;
   arrayOop      _sites;
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Jul 18 10:50:57 2012 -0700
@@ -804,7 +804,15 @@
   set_int(env, config, "threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset()));
   set_int(env, config, "threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset()));
   set_int(env, config, "threadMultiNewArrayStorageOffset", in_bytes(JavaThread::graal_multinewarray_storage_offset()));
+  set_long(env, config, "safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size())));
+  set_boolean(env, config, "isPollingPageFar", Assembler::is_polling_page_far());
   set_int(env, config, "classMirrorOffset", in_bytes(Klass::java_mirror_offset()));
+  set_int(env, config, "runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes);
+  set_int(env, config, "klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset()));
+  set_int(env, config, "klassOopOffset", java_lang_Class::klass_offset_in_bytes());
+  set_int(env, config, "graalMirrorKlassOffset", in_bytes(Klass::graal_mirror_offset()));
+  set_int(env, config, "nmethodEntryOffset", nmethod::verified_entry_point_offset());
+  set_int(env, config, "methodCompiledEntryOffset", in_bytes(methodOopDesc::from_compiled_offset()));
   
   set_int(env, config, "methodDataOopDataOffset", in_bytes(methodDataOopDesc::data_offset()));
   set_int(env, config, "methodDataOopTrapHistoryOffset", in_bytes(methodDataOopDesc::trap_history_offset()));
@@ -824,14 +832,10 @@
 
   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, "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)));
   set_long(env, config, "newMultiArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_multi_array_id)));
-  set_long(env, config, "loadKlassStub", VmIds::addStub(Runtime1::entry_for(Runtime1::load_klass_patching_id)));
-  set_long(env, config, "accessFieldStub", VmIds::addStub(Runtime1::entry_for(Runtime1::access_field_patching_id)));
-  set_long(env, config, "resolveStaticCallStub", VmIds::addStub(SharedRuntime::get_resolve_static_call_stub()));
   set_long(env, config, "inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub()));
   set_long(env, config, "handleExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id)));
   set_long(env, config, "handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack()));
@@ -839,16 +843,8 @@
   set_long(env, config, "monitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorexit_id)));
   set_long(env, config, "fastMonitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_monitorenter_id)));
   set_long(env, config, "fastMonitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_monitorexit_id)));
-  set_long(env, config, "safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size())));
-  set_int(env, config, "runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes);
-  set_int(env, config, "klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset()));
-  set_int(env, config, "graalMirrorKlassOffset", in_bytes(Klass::graal_mirror_offset()));
-  set_int(env, config, "klassOopOffset", java_lang_Class::klass_offset_in_bytes());
-  set_int(env, config, "methodCompiledEntryOffset", in_bytes(methodOopDesc::from_compiled_offset()));
+  set_long(env, config, "verifyOopStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_verify_oop_id)));
 
-  set_boolean(env, config, "isPollingPageFar", Assembler::is_polling_page_far());
-
-  set_int(env, config, "nmethodEntryOffset", nmethod::verified_entry_point_offset());
 
   BarrierSet* bs = Universe::heap()->barrier_set();
   switch (bs->kind()) {
@@ -879,16 +875,16 @@
   return config;
 }
 
-// public HotSpotCompiledMethod installMethod(HotSpotTargetMethod targetMethod, boolean installCode);
-JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_installMethod(JNIEnv *jniEnv, jobject, jobject targetMethod, jboolean install_code, jobject info) {
+// public HotSpotCompiledMethod installMethod(HotSpotCompilationResult comp, boolean installCode);
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_installMethod(JNIEnv *jniEnv, jobject, jobject compResult, jboolean install_code, jobject info) {
   VM_ENTRY_MARK;
   ResourceMark rm;
   HandleMark hm;
-  Handle targetMethodHandle = JNIHandles::resolve(targetMethod);
+  Handle compResultHandle = JNIHandles::resolve(compResult);
   nmethod* nm = NULL;
   Arena arena;
   ciEnv env(&arena);
-  CodeInstaller installer(targetMethodHandle, nm, install_code != 0);
+  CodeInstaller installer(compResultHandle, nm, install_code != 0);
 
   if (info != NULL) {
     arrayOop codeCopy = oopFactory::new_byteArray(nm->code_size(), CHECK_0);
@@ -903,7 +899,7 @@
     Handle obj = instanceKlass::cast(HotSpotCompiledMethod::klass())->allocate_permanent_instance(CHECK_NULL);
     assert(obj() != NULL, "must succeed in allocating instance");
     HotSpotCompiledMethod::set_nmethod(obj, (jlong) nm);
-    HotSpotCompiledMethod::set_method(obj, HotSpotTargetMethod::method(targetMethod));
+    HotSpotCompiledMethod::set_method(obj, HotSpotCompilationResult::method(compResult));
     nm->set_graal_compiled_method(obj());
     return JNIHandles::make_local(obj());
   } else {
@@ -1070,15 +1066,15 @@
 #define RESOLVED_FIELD  "Lcom/oracle/graal/api/meta/ResolvedJavaField;"
 #define CONSTANT_POOL   "Lcom/oracle/graal/api/meta/ConstantPool;"
 #define EXCEPTION_HANDLERS "[Lcom/oracle/graal/api/meta/ExceptionHandler;"
-#define TARGET_METHOD   "Lcom/oracle/graal/hotspot/HotSpotTargetMethod;"
+#define HS_COMP_RESULT  "Lcom/oracle/graal/hotspot/HotSpotCompilationResult;"
 #define CONFIG          "Lcom/oracle/graal/hotspot/HotSpotVMConfig;"
 #define HS_METHOD       "Lcom/oracle/graal/hotspot/meta/HotSpotMethod;"
 #define HS_COMP_METHOD  "Lcom/oracle/graal/hotspot/meta/HotSpotCompiledMethod;"
 #define HS_CODE_INFO    "Lcom/oracle/graal/hotspot/meta/HotSpotCodeInfo;"
 #define METHOD_DATA     "Lcom/oracle/graal/hotspot/meta/HotSpotMethodData;"
-#define CI_CONSTANT     "Lcom/oracle/graal/api/meta/Constant;"
-#define CI_KIND         "Lcom/oracle/graal/api/meta/Kind;"
-#define CI_RUNTIME_CALL "Lcom/oracle/graal/api/code/RuntimeCall;"
+#define CONSTANT        "Lcom/oracle/graal/api/meta/Constant;"
+#define KIND            "Lcom/oracle/graal/api/meta/Kind;"
+#define RUNTIME_CALL    "Lcom/oracle/graal/api/code/RuntimeCall;"
 #define STRING          "Ljava/lang/String;"
 #define OBJECT          "Ljava/lang/Object;"
 #define CLASS           "Ljava/lang/Class;"
@@ -1095,12 +1091,12 @@
   {CC"JavaMethod_invocationCount",          CC"("RESOLVED_METHOD")I",                             FN_PTR(JavaMethod_1invocationCount)},
   {CC"JavaMethod_hasCompiledCode",          CC"("RESOLVED_METHOD")Z",                             FN_PTR(JavaMethod_1hasCompiledCode)},
   {CC"JavaMethod_getCompiledCodeSize",      CC"("RESOLVED_METHOD")I",                             FN_PTR(JavaMethod_1getCompiledCodeSize)},
-  {CC"Signature_lookupType",            CC"("STRING RESOLVED_TYPE"Z)"TYPE,                    FN_PTR(Signature_1lookupType)},
-  {CC"ConstantPool_lookupConstant",     CC"("RESOLVED_TYPE"I)"OBJECT,                         FN_PTR(ConstantPool_1lookupConstant)},
-  {CC"ConstantPool_lookupMethod",       CC"("RESOLVED_TYPE"IB)"METHOD,                        FN_PTR(ConstantPool_1lookupMethod)},
-  {CC"ConstantPool_lookupType",         CC"("RESOLVED_TYPE"I)"TYPE,                           FN_PTR(ConstantPool_1lookupType)},
-  {CC"ConstantPool_loadReferencedType", CC"("RESOLVED_TYPE"IB)V",                             FN_PTR(ConstantPool_1loadReferencedType)},
-  {CC"ConstantPool_lookupField",        CC"("RESOLVED_TYPE"IB)"FIELD,                         FN_PTR(ConstantPool_1lookupField)},
+  {CC"Signature_lookupType",                CC"("STRING RESOLVED_TYPE"Z)"TYPE,                    FN_PTR(Signature_1lookupType)},
+  {CC"ConstantPool_lookupConstant",         CC"("RESOLVED_TYPE"I)"OBJECT,                         FN_PTR(ConstantPool_1lookupConstant)},
+  {CC"ConstantPool_lookupMethod",           CC"("RESOLVED_TYPE"IB)"METHOD,                        FN_PTR(ConstantPool_1lookupMethod)},
+  {CC"ConstantPool_lookupType",             CC"("RESOLVED_TYPE"I)"TYPE,                           FN_PTR(ConstantPool_1lookupType)},
+  {CC"ConstantPool_loadReferencedType",     CC"("RESOLVED_TYPE"IB)V",                             FN_PTR(ConstantPool_1loadReferencedType)},
+  {CC"ConstantPool_lookupField",            CC"("RESOLVED_TYPE"IB)"FIELD,                         FN_PTR(ConstantPool_1lookupField)},
   {CC"JavaType_resolveMethodImpl",          CC"("RESOLVED_TYPE STRING STRING")"METHOD,            FN_PTR(JavaType_3resolveMethodImpl)},
   {CC"JavaType_isSubtypeOf",                CC"("RESOLVED_TYPE TYPE")Z",                          FN_PTR(JavaType_2isSubtypeOf)},
   {CC"JavaType_leastCommonAncestor",        CC"("RESOLVED_TYPE RESOLVED_TYPE")"TYPE,              FN_PTR(JavaType_2leastCommonAncestor)},
@@ -1110,18 +1106,18 @@
   {CC"JavaType_arrayOf",                    CC"("RESOLVED_TYPE")"TYPE,                            FN_PTR(JavaType_1arrayOf)},
   {CC"JavaType_fields",                     CC"("RESOLVED_TYPE")["RESOLVED_FIELD,                 FN_PTR(JavaType_1fields)},
   {CC"JavaType_isInitialized",              CC"("RESOLVED_TYPE")Z",                               FN_PTR(JavaType_1isInitialized)},
-  {CC"getPrimitiveArrayType",             CC"("CI_KIND")"TYPE,                                  FN_PTR(getPrimitiveArrayType)},
-  {CC"getMaxCallTargetOffset",            CC"("CI_RUNTIME_CALL")J",                             FN_PTR(getMaxCallTargetOffset)},
-  {CC"getType",                           CC"("CLASS")"TYPE,                                    FN_PTR(getType)},
-  {CC"getConfiguration",                  CC"()"CONFIG,                                         FN_PTR(getConfiguration)},
-  {CC"installMethod",                     CC"("TARGET_METHOD"Z"HS_CODE_INFO")"HS_COMP_METHOD,   FN_PTR(installMethod)},
-  {CC"disassembleNative",                 CC"([BJ)"STRING,                                      FN_PTR(disassembleNative)},
+  {CC"getPrimitiveArrayType",               CC"("KIND")"TYPE,                                     FN_PTR(getPrimitiveArrayType)},
+  {CC"getMaxCallTargetOffset",              CC"("RUNTIME_CALL")J",                                FN_PTR(getMaxCallTargetOffset)},
+  {CC"getType",                             CC"("CLASS")"TYPE,                                    FN_PTR(getType)},
+  {CC"getConfiguration",                    CC"()"CONFIG,                                         FN_PTR(getConfiguration)},
+  {CC"installMethod",                       CC"("HS_COMP_RESULT"Z"HS_CODE_INFO")"HS_COMP_METHOD,  FN_PTR(installMethod)},
+  {CC"disassembleNative",                   CC"([BJ)"STRING,                                      FN_PTR(disassembleNative)},
   {CC"JavaMethod_toStackTraceElement",      CC"("RESOLVED_METHOD"I)"STACK_TRACE_ELEMENT,          FN_PTR(JavaMethod_1toStackTraceElement)},
-  {CC"executeCompiledMethod",             CC"("HS_COMP_METHOD OBJECT OBJECT OBJECT")"OBJECT,    FN_PTR(executeCompiledMethod)},
-  {CC"executeCompiledMethodVarargs",      CC"("HS_COMP_METHOD "["OBJECT")"OBJECT,               FN_PTR(executeCompiledMethodVarargs)},
+  {CC"executeCompiledMethod",               CC"("HS_COMP_METHOD OBJECT OBJECT OBJECT")"OBJECT,    FN_PTR(executeCompiledMethod)},
+  {CC"executeCompiledMethodVarargs",        CC"("HS_COMP_METHOD "["OBJECT")"OBJECT,               FN_PTR(executeCompiledMethodVarargs)},
   {CC"JavaMethod_vtableEntryOffset",        CC"("RESOLVED_METHOD")I",                             FN_PTR(JavaMethod_vtableEntryOffset)},
-  {CC"getDeoptedLeafGraphIds",            CC"()[J",                                             FN_PTR(getDeoptedLeafGraphIds)},
-  {CC"decodePC",                          CC"(J)"STRING,                                        FN_PTR(decodePC)},
+  {CC"getDeoptedLeafGraphIds",              CC"()[J",                                             FN_PTR(getDeoptedLeafGraphIds)},
+  {CC"decodePC",                            CC"(J)"STRING,                                        FN_PTR(decodePC)},
 };
 
 int CompilerToVM_methods_count() {
--- a/src/share/vm/graal/graalJavaAccess.hpp	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Wed Jul 18 10:50:57 2012 -0700
@@ -95,15 +95,12 @@
     long_field(HotSpotCodeInfo, start)                                                  \
     oop_field(HotSpotCodeInfo, code, "[B")                                              \
   end_class                                                                             \
-  start_class(HotSpotProxy)                                                             \
-    static_oop_field(HotSpotProxy, DUMMY_CONSTANT_OBJ, "Ljava/lang/Long;")              \
-  end_class                                                                             \
-  start_class(HotSpotTargetMethod)                                                      \
-    oop_field(HotSpotTargetMethod, targetMethod, "Lcom/oracle/graal/api/code/CompilationResult;") \
-    oop_field(HotSpotTargetMethod, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;") \
-    oop_field(HotSpotTargetMethod, name, "Ljava/lang/String;")                          \
-    oop_field(HotSpotTargetMethod, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;") \
-    oop_field(HotSpotTargetMethod, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;") \
+  start_class(HotSpotCompilationResult)                                                      \
+    oop_field(HotSpotCompilationResult, comp, "Lcom/oracle/graal/api/code/CompilationResult;") \
+    oop_field(HotSpotCompilationResult, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;") \
+    oop_field(HotSpotCompilationResult, name, "Ljava/lang/String;")                          \
+    oop_field(HotSpotCompilationResult, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;") \
+    oop_field(HotSpotCompilationResult, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;") \
   end_class                                                                             \
   start_class(ExceptionHandler)                                                  \
     int_field(ExceptionHandler, startBCI)                                        \
--- a/src/share/vm/graal/graalVMToInterpreter.cpp	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/vm/graal/graalVMToInterpreter.cpp	Wed Jul 18 10:50:57 2012 -0700
@@ -237,7 +237,7 @@
   if (is_java_primitive(expected_result_type)) {
     unbox_primitive(&boxed_result, result);
   } else if (expected_result_type == T_OBJECT || expected_result_type == T_ARRAY) {
-    result->set_jobject(result->get_jobject());
+    result->set_jobject(boxed_result.get_jobject());
   }
 }
 
--- a/src/share/vm/runtime/javaCalls.cpp	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/vm/runtime/javaCalls.cpp	Wed Jul 18 10:50:57 2012 -0700
@@ -445,6 +445,7 @@
   if (thread->high_level_interpreter_in_vm() && !method->is_native() && Interpreter::contains(entry_point)) {
     assert(nm == NULL || !nm->is_alive(), "otherwise nm should be invoked");
     VMToInterpreter::execute(result, m, args, result->get_type(), thread);
+    oop_result_flag = false; // result already holds the correct value
   } else
 #endif
   // do call
--- a/src/share/vm/runtime/sharedRuntime.cpp	Thu Jul 05 11:48:30 2012 +0200
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Wed Jul 18 10:50:57 2012 -0700
@@ -1697,6 +1697,8 @@
 IRT_LEAF(void, SharedRuntime::fixup_callers_callsite(methodOopDesc* method, address caller_pc))
   methodOop moop(method);
 
+  assert(moop->is_oop(false) && moop->is_method(), "method oop from call site is invalid");
+
   address entry_point = moop->from_compiled_entry();
 
   // It's possible that deoptimization can occur at a call site which hasn't
--- a/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -49,7 +49,7 @@
     public BytecodeNode(InputBytecode bytecode, InputGraph graph, String bciValue) {
 
         super(Children.LEAF);
-        this.setDisplayName(bytecode.getBci() + " " + bytecode.getName());
+        String displayName = bytecode.getBci() + " " + bytecode.getName() + " " + bytecode.getOperands();
 
         bciValue = bytecode.getBci() + " " + bciValue;
         bciValue = bciValue.trim();
@@ -62,8 +62,14 @@
             for (InputNode n : nodeList) {
                 nodes.add(n);
             }
-            this.setDisplayName(this.getDisplayName() + " (" + nodes.size() + " nodes)");
+            displayName += " (" + nodes.size() + " nodes)";
         }
+        
+        if (bytecode.getComment() != null) {
+            displayName += " // " + bytecode.getComment();
+        }
+        
+        this.setDisplayName(displayName);
     }
 
     @Override
--- a/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java	Wed Jul 18 10:50:57 2012 -0700
@@ -91,7 +91,7 @@
     /**
      * Gets default instance. Do not use directly: reserved for *.settings files only,
      * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
-     * To obtain the singleton instance, use {@link findInstance}.
+     * To obtain the singleton instance, use {@link #findInstance}.
      */
     public static synchronized BytecodeViewTopComponent getDefault() {
         if (instance == null) {
--- a/visualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java	Wed Jul 18 10:50:57 2012 -0700
@@ -31,11 +31,15 @@
 
     private int bci;
     private String name;
+    private String operands;
+    private String comment;
     private InputMethod inlined;
 
-    public InputBytecode(int bci, String name) {
+    public InputBytecode(int bci, String name, String operands, String comment) {
         this.bci = bci;
         this.name = name;
+        this.operands = operands;
+        this.comment = comment;
     }
 
     public InputMethod getInlined() {
@@ -53,4 +57,12 @@
     public String getName() {
         return name;
     }
+
+    public String getOperands() {
+        return operands;
+    }
+
+    public String getComment() {
+        return comment;
+    }
 }
--- a/visualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java	Thu Jul 05 11:48:30 2012 +0200
+++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java	Wed Jul 18 10:50:57 2012 -0700
@@ -26,6 +26,8 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  *
@@ -109,31 +111,38 @@
     }
 
     public void setBytecodes(String text) {
-
+        Pattern instruction = Pattern.compile("\\s*(\\d+)\\s*:?\\s*(\\w+)\\s*(.*)(?://(.*))?");
         String[] strings = text.split("\n");
-        int oldNumber = -1;
+        int oldBci = -1;
         for (String s : strings) {
-
-            if (s.length() > 0 && Character.isDigit(s.charAt(0))) {
-                s = s.trim();
-                int spaceIndex = s.indexOf(' ');
-                String numberString = s.substring(0, spaceIndex);
-                String tmpName = s.substring(spaceIndex + 1, s.length());
+            s = s.trim();
+            if (s.length() != 0) {
+                final Matcher matcher = instruction.matcher(s);
+                if (matcher.matches()) {
+                    String bciString = matcher.group(1);
+                    String opcode = matcher.group(2);
+                    String operands = matcher.group(3).trim();
+                    String comment = matcher.group(4);
+                    if (comment != null) {
+                        comment = comment.trim();
+                    }
 
-                int number = -1;
-                number = Integer.parseInt(numberString);
+                    int bci = Integer.parseInt(bciString);
 
-                // assert correct order of bytecodes
-                assert number > oldNumber;
+                    // assert correct order of bytecodes
+                    assert bci > oldBci;
+
+                    InputBytecode bc = new InputBytecode(bci, opcode, operands, comment);
+                    bytecodes.add(bc);
 
-                InputBytecode bc = new InputBytecode(number, tmpName);
-                bytecodes.add(bc);
-
-                for (InputMethod m : inlined) {
-                    if (m.getBci() == number) {
-                        bc.setInlined(m);
-                        break;
+                    for (InputMethod m : inlined) {
+                        if (m.getBci() == bci) {
+                            bc.setInlined(m);
+                            break;
+                        }
                     }
+                } else {
+                    System.out.println("no match: " + s);
                 }
             }
         }