changeset 13965:d68f5d0c97f0

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Mon, 17 Feb 2014 13:48:41 +0100
parents 8df361535530 (current diff) 4eda2fa64da6 (diff)
children be0d961e3a88
files CHANGELOG.md graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionHandle.java graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionInterface.java graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionPointer.java graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeLibraryHandle.java graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/node/AMD64RawNativeCallNode.java graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/util/InstallUtil.java graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/util/NativeCallStubGraphBuilder.java graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/LibCallTest.java graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/MathLibCallTest.java graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/StdLibCallTest.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/UnoptimizedCallTarget.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/DefaultCallTargetSubstitutions.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/FrameFactory.java graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProbe.java graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyTraceProbe.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLCallNode.java
diffstat 150 files changed, 4282 insertions(+), 1950 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG.md	Thu Feb 06 17:41:51 2014 +0100
+++ b/CHANGELOG.md	Mon Feb 17 13:48:41 2014 +0100
@@ -1,19 +1,24 @@
 # GraalVM Changelog
 
-## Tip
+## `tip`
+### Graal
+* ...
 
-* Graal
-  * ...
-* Truffle
-  * ...
+### Truffle
+* ...
 
 ## Version 0.1
 5-Feb-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/b124e22eb772)
-* Graal
-  * Initial version of a dynamic Java compiler written in Java.
-  * Support for multiple co-existing GPU backends ([GRAAL-1](https://bugs.openjdk.java.net/browse/GRAAL-1)).
-  * Fixed a compiler bug when running RuneScape ([Graal-7](https://bugs.openjdk.java.net/browse/GRAAL-7)).
-  * Bug fixes ([GRAAL-4](https://bugs.openjdk.java.net/browse/GRAAL-4), [GRAAL-5](https://bugs.openjdk.java.net/browse/GRAAL-5)).
-* Truffle
-  * Initial version of a multi-language framework on top of Graal.
-  * Update of the [Truffle inlining API](http://mail.openjdk.java.net/pipermail/graal-dev/2014-January/001516.html).
+
+### Graal
+
+* Initial version of a dynamic Java compiler written in Java.
+* Support for multiple co-existing GPU backends ([GRAAL-1](https://bugs.openjdk.java.net/browse/GRAAL-1)).
+* Fixed a compiler bug when running RuneScape ([GRAAL-7](https://bugs.openjdk.java.net/browse/GRAAL-7)).
+* Bug fixes ([GRAAL-4](https://bugs.openjdk.java.net/browse/GRAAL-4), [GRAAL-5](https://bugs.openjdk.java.net/browse/GRAAL-5)).
+
+### Truffle
+
+* Initial version of a multi-language framework on top of Graal.
+* Update of the [Truffle Inlining API](http://mail.openjdk.java.net/pipermail/graal-dev/2014-January/001516.html).
+
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Mon Feb 17 13:48:41 2014 +0100
@@ -116,6 +116,26 @@
         this.numStack = numStack;
         this.numLocks = numLocks;
         assert !rethrowException || numStack == 1 : "must have exception on top of the stack";
+        assert validateFormat();
+    }
+
+    /**
+     * Ensure that the frame state is formatted as expected by the JVM, with null or Illegal in the
+     * slot following a double word item. This should really be checked in FrameState itself but
+     * because of Word type rewriting that can't be done. If a frame makes it into this code, then
+     * could be materialized by the JVM so it must follow the rules. it
+     */
+    private boolean validateFormat() {
+        for (int i = 0; i < numLocals + numStack; i++) {
+            if (values[i] != null) {
+                Kind kind = values[i].getKind();
+                if (kind == Kind.Long || kind == Kind.Double) {
+                    assert values.length > i + 1 : String.format("missing second word %s", this);
+                    assert values[i + 1] == null || values[i + 1].getKind() == Kind.Illegal;
+                }
+            }
+        }
+        return true;
     }
 
     /**
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Mon Feb 17 13:48:41 2014 +0100
@@ -288,6 +288,14 @@
             }
         }
 
+        public int getAlignment() {
+            if (externalData instanceof ConstantData) {
+                return ((ConstantData) externalData).getAlignment();
+            } else {
+                return 0;
+            }
+        }
+
         public String getDataString() {
             if (inlineData != null) {
                 return inlineData.toString();
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionHandle.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionHandle.java	Mon Feb 17 13:48:41 2014 +0100
@@ -23,28 +23,25 @@
 package com.oracle.graal.api.code;
 
 /**
- * The handle of a native foreign function. Use a {@code NativeFunctionHandle} to invoke native
- * target functions.
- * <p>
- * The user of a {@code NativeFunctionHandle} has to pack the boxed arguments into an
- * {@code Object[]} according to the ABI of the target platform (e.g. Unix AMD64 system:
- * {@link "http://www.uclibc.org/docs/psABI-x86_64.pdf"}). The {@code NativeFunctionHandle} unboxes
- * the arguments and places them into the right location (register / stack) according to the ABI.
- * <p>
- * A {@code NativeFunctionHandle} returns the boxed return value of the native target function. The
- * boxed value is the return value as specified by the ABI.
+ * A handle that can be used to {@linkplain #call(Object[]) call} a native function.
  */
 public interface NativeFunctionHandle {
 
     /**
-     * Calls the native foreign function.
+     * Calls the native function.
+     * <p>
+     * The caller is responsible for ensuring {@code args} comply with the platform ABI (e.g. <a
+     * href="http://www.uclibc.org/docs/psABI-x86_64.pdf"> Unix AMD64 ABI</a>). If the library
+     * function has struct parameters, the fields of the struct must be passed as individual
+     * arguments.
      * 
-     * @param args the arguments that will be passed to the native foreign function
+     * @param args the arguments that will be passed to the native function
+     * @return boxed return value of the function call
      */
-    Object call(Object[] args);
+    Object call(Object... args);
 
     /**
-     * Returns the installed code of the call stub for the native foreign function call.
+     * Returns the installed code of the call stub for the native function call.
      * 
      * @return the installed code of the native call stub
      */
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionInterface.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionInterface.java	Mon Feb 17 13:48:41 2014 +0100
@@ -23,91 +23,100 @@
 package com.oracle.graal.api.code;
 
 /**
- * Interface to resolve a {@code NativeFunctionHandle} or a {@code NativeFunctionPointer} to a
- * native foreign function and a {@code NativeLibraryHandle} of a library. A
- * {@code NativeFunctionPointer} wraps the raw function pointer. A {@code NativeFunctionHandle} is a
- * callable representation of a native target function in Java.
- * <p>
- * To resolve a {@code NativeFunctionHandle}, one has to provide the signature of the native target
- * function according to the calling convention of the target platform (e.g. Unix AMD64:
- * {@link "http://www.uclibc.org/docs/psABI-x86_64.pdf"}). The signature contains the type (e.g.
- * {@code int.class} for a C integer, ( {@code long.class} for a 64bit pointer) of each value, which
- * is passed to the native target function.
+ * Interface to get a {@linkplain NativeFunctionHandle handle} or {@linkplain NativeFunctionPointer
+ * pointer} to a native function or a {@linkplain NativeLibraryHandle handle} to an open native
+ * library.
  */
 public interface NativeFunctionInterface {
 
     /**
-     * Resolves and returns a library handle.
+     * Resolves and returns a handle to an open native library. This method will open the library
+     * only if it is not already open.
      * 
      * @param libPath the absolute path to the library
      * @return the resolved library handle
+     * @throws UnsatisfiedLinkError if the library could not be found or opened
      */
     NativeLibraryHandle getLibraryHandle(String libPath);
 
     /**
-     * Resolves the {@code NativeFunctionHandle} of a native function that can be called. Use a
-     * {@code NativeFunctionHandle} to invoke the native target function.
+     * Determines if the underlying platform/runtime supports the notion of a default library search
+     * path. For example, on *nix systems, this is typically defined by the {@code LD_LIBRARY_PATH}
+     * environment variable.
+     */
+    boolean isDefaultLibrarySearchSupported();
+
+    /**
+     * Resolves the function pointer {@code NativeFunctionPointer} of a native function.
      * 
-     * @param libraryHandle the handle to a resolved library
-     * @param functionName the name of the function to be resolved
+     * @param libraries the ordered list of libraries to search for the function
+     * @param name the name of the function to be resolved
+     * @return a pointer to the native function
+     * @throws UnsatisfiedLinkError if the function could not be resolved
+     */
+    NativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraries, String name);
+
+    /**
+     * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called
+     * with a given signature. The signature contains the types of the arguments that will be passed
+     * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}.
+     * 
+     * @param library the handle to a resolved library
+     * @param name the name of the function to be resolved
      * @param returnType the type of the return value
      * @param argumentTypes the types of the arguments
-     * @return the function handle of the native foreign function
+     * @return the function handle of the native function
+     * @throws UnsatisfiedLinkError if the function handle could not be resolved
      */
-    NativeFunctionHandle getFunctionHandle(NativeLibraryHandle libraryHandle, String functionName, Class returnType, Class[] argumentTypes);
-
-    /**
-     * Resolves the {@code NativeFunctionHandle} of a native function that can be called. Use a
-     * {@code NativeFunctionHandle} to invoke the native target function.
-     * 
-     * @param functionPointer the function pointer
-     * @param returnType the type of the return value
-     * @param argumentTypes the types of the arguments
-     * @return the function handle of the native foreign function
-     */
-    NativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class[] argumentTypes);
+    NativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class returnType, Class... argumentTypes);
 
     /**
-     * Resolves the function pointer {@code NativeFunctionPointer} of a native function. A
-     * {@code NativeFunctionPointer} wraps the raw pointer value.
+     * Resolves a function pointer to a {@linkplain NativeFunctionHandle handle} that can be called
+     * with a given signature. The signature contains the types of the arguments that will be passed
+     * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}.
      * 
-     * @param libraryHandles the handles to a various resolved library, the first library containing
-     *            the method wins
-     * @param functionName the name of the function to be resolved
-     * @return the function handle of the native foreign function
+     * @param functionPointer a function pointer
+     * @param returnType the type of the return value
+     * @param argumentTypes the types of the arguments
+     * @return the function handle of the native function
+     * @throws UnsatisfiedLinkError the function handle could not be created
      */
-    NativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraryHandles, String functionName);
+    NativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes);
 
     /**
-     * Resolves the {@code NativeFunctionHandle} of a native function that can be called. Use a
-     * {@code NativeFunctionHandle} to invoke the native target function.
+     * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called
+     * with a given signature. The signature contains the types of the arguments that will be passed
+     * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}.
      * 
-     * @param libraryHandles the handles to a various resolved library, the first library containing
-     *            the method wins
-     * @param functionName the name of the function to be resolved
+     * @param libraries the ordered list of libraries to search for the function
+     * @param name the name of the function to be resolved
      * @param returnType the type of the return value
      * @param argumentTypes the types of the arguments
-     * @return the function handle of the native foreign function
+     * @return the function handle of the native function
+     * @throws UnsatisfiedLinkError if the function handle could not be created
      */
-    NativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraryHandles, String functionName, Class returnType, Class[] argumentTypes);
+    NativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class returnType, Class... argumentTypes);
 
     /**
-     * Resolves the {@code NativeFunctionHandle} of a native function that can be called. Use a
-     * {@code NativeFunctionHandle} to invoke the native target function.
+     * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called
+     * with a given signature. The signature contains the types of the arguments that will be passed
+     * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}.
      * 
-     * @param functionName the name of the function to be resolved
+     * @param name the name of the function to be resolved
      * @param returnType the type of the return value
      * @param argumentTypes the types of the arguments
-     * @return the function handle of the native foreign function
+     * @return the function handle of the native function
+     * @throws UnsatisfiedLinkError if default library searching is not
+     *             {@linkplain #isDefaultLibrarySearchSupported() supported} or if the function
+     *             could not be resolved
      */
-    NativeFunctionHandle getFunctionHandle(String functionName, Class returnType, Class[] argumentTypes);
+    NativeFunctionHandle getFunctionHandle(String name, Class returnType, Class... argumentTypes);
 
     /**
-     * Creates {@code NativeFunctionPointer} from raw value. A {@code NativeFunctionPointer} wraps
-     * the raw pointer value.
+     * Creates a {@link NativeFunctionPointer} from a raw value.
      * 
-     * @param rawValue Raw pointer value
-     * @return {@code NativeFunctionPointer} of the raw pointer
+     * @param rawValue raw function pointer
+     * @return {@code NativeFunctionPointer} for {@code rawValue}
      */
     NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue);
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionPointer.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionPointer.java	Mon Feb 17 13:48:41 2014 +0100
@@ -23,32 +23,19 @@
 package com.oracle.graal.api.code;
 
 /**
- * Wraps the raw function pointer value.
+ * An opaque representation of a native function pointer.
  * <p>
- * Use the {@code NativeFunctionInterface} to resolve a {@code NativeFunctionHandle} of this pointer
- * to invoke the native target function.
+ * Use {@code NativeFunctionInterface#getFunctionHandle(NativeFunctionPointer, Class, Class...)} to
+ * get a handle enabling the native function to be {@linkplain NativeFunctionHandle#call(Object...)
+ * called}.
  */
 public interface NativeFunctionPointer {
 
     /**
-     * Returns whether the pointer is valid.
-     * 
-     * @return true if the pointer is valid
-     */
-    boolean isValid();
-
-    /**
-     * Returns function pointer as raw value.
-     * 
-     * @return raw value of function pointer
-     */
-    long asRawValue();
-
-    /**
      * Returns the name of the function.
      * 
      * @return name of the function
      */
-    String getFunctionName();
+    String getName();
 
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeLibraryHandle.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeLibraryHandle.java	Mon Feb 17 13:48:41 2014 +0100
@@ -23,24 +23,15 @@
 package com.oracle.graal.api.code;
 
 /**
- * The library handle of the native library.
- * <p>
- * The {@code NativeFunctionInterface} can use a {@code NativeLibraryHandle} to look up a
- * {@code NativeFunctionPointer} or a {@code NativeFunctionHandle} in this library.
+ * An opaque representation of a native library handle. A handle is obtained via
+ * {@link NativeFunctionInterface#getLibraryHandle(String)}. A handle is used to resolve a string to
+ * a {@linkplain NativeFunctionInterface#getFunctionHandle(String, Class, Class...) handle} or
+ * {@linkplain NativeFunctionInterface#getFunctionPointer(NativeLibraryHandle[], String) pointer}.
  */
 public interface NativeLibraryHandle {
-
     /**
-     * Returns whether the handle is valid.
-     * 
-     * @return true if the handle is valid
+     * Gets a name for this library. This may be the path for the file from which the library was
+     * loaded.
      */
-    boolean isValid();
-
-    /**
-     * Returns function pointer as raw value.
-     * 
-     * @return raw value of function pointer
-     */
-    long asRawValue();
+    String getName();
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java	Mon Feb 17 13:48:41 2014 +0100
@@ -86,6 +86,29 @@
         return frameRefMap != null && frameRefMap.size() > 0;
     }
 
+    public interface Iterator {
+        void register(int idx, boolean narrow);
+
+        void stackSlot(int idx, boolean narrow1, boolean narrow2);
+    }
+
+    public void iterate(Iterator iterator) {
+        if (hasRegisterRefMap()) {
+            for (int i = 0; i < registerRefMap.size() / 2; i++) {
+                if (registerRefMap.get(2 * i)) {
+                    iterator.register(i, registerRefMap.get(2 * i + 1));
+                }
+            }
+        }
+        if (hasFrameRefMap()) {
+            for (int i = 0; i < frameRefMap.size() / 3; i++) {
+                if (frameRefMap.get(3 * i)) {
+                    iterator.stackSlot(i, frameRefMap.get(3 * i + 1), frameRefMap.get(3 * i + 2));
+                }
+            }
+        }
+    }
+
     private static class NumberedRefMapFormatter implements RefMapFormatter {
 
         public String formatStackSlot(int frameRefMapIndex) {
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Mon Feb 17 13:48:41 2014 +0100
@@ -290,6 +290,7 @@
         "reprofile",
         "getCompilerStorage",
         "canBeInlined",
+        "shouldBeInlined",
         "getLineNumberTable",
         "getLocalVariableTable",
         "isInVirtualMethodTable",
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Mon Feb 17 13:48:41 2014 +0100
@@ -72,12 +72,12 @@
     private final Class primitiveJavaClass;
     private final Class boxedJavaClass;
 
-    private Kind(char typeChar, String javaName, boolean isStackInt, Class primitiveJavaClass, Class boxedJavasClass) {
+    private Kind(char typeChar, String javaName, boolean isStackInt, Class primitiveJavaClass, Class boxedJavaClass) {
         this.typeChar = typeChar;
         this.javaName = javaName;
         this.isStackInt = isStackInt;
         this.primitiveJavaClass = primitiveJavaClass;
-        this.boxedJavaClass = boxedJavasClass;
+        this.boxedJavaClass = boxedJavaClass;
         assert primitiveJavaClass == null || javaName.equals(primitiveJavaClass.getName());
     }
 
@@ -255,19 +255,30 @@
 
     /**
      * Marker interface for types that should be {@linkplain Kind#format(Object) formatted} with
-     * their {@link Object#toString()} value.
+     * their {@link Object#toString()} value. Calling {@link Object#toString()} on other objects
+     * poses a security risk because it can potentially call user code.
      */
     public interface FormatWithToString {
     }
 
     /**
+     * Classes for which invoking {@link Object#toString()} does not run user code.
+     */
+    private static boolean isToStringSafe(Class c) {
+        return c == Boolean.class || c == Byte.class || c == Character.class || c == Short.class || c == Integer.class || c == Float.class || c == Long.class || c == Double.class;
+    }
+
+    /**
      * Gets a formatted string for a given value of this kind.
      * 
      * @param value a value of this kind
      * @return a formatted string for {@code value} based on this kind
      */
     public String format(Object value) {
-        if (this == Kind.Object) {
+        if (isPrimitive()) {
+            assert isToStringSafe(value.getClass());
+            return value.toString();
+        } else {
             if (value == null) {
                 return "null";
             } else {
@@ -280,18 +291,20 @@
                     }
                 } else if (value instanceof JavaType) {
                     return "JavaType:" + MetaUtil.toJavaName((JavaType) value);
-                } else if (value instanceof Enum || value instanceof FormatWithToString || value instanceof Number) {
+                } else if (value instanceof Enum) {
+                    return MetaUtil.getSimpleName(value.getClass(), true) + ":" + ((Enum) value).name();
+                } else if (value instanceof FormatWithToString) {
                     return MetaUtil.getSimpleName(value.getClass(), true) + ":" + String.valueOf(value);
                 } else if (value instanceof Class<?>) {
                     return "Class:" + ((Class<?>) value).getName();
+                } else if (isToStringSafe(value.getClass())) {
+                    return value.toString();
                 } else if (value.getClass().isArray()) {
                     return formatArray(value);
                 } else {
                     return MetaUtil.getSimpleName(value.getClass(), true) + "@" + System.identityHashCode(value);
                 }
             }
-        } else {
-            return value.toString();
         }
     }
 
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Mon Feb 17 13:48:41 2014 +0100
@@ -185,6 +185,8 @@
      */
     boolean canBeInlined();
 
+    boolean shouldBeInlined();
+
     /**
      * Returns the LineNumberTable of this method or null if this method does not have a line
      * numbers table.
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Feb 17 13:48:41 2014 +0100
@@ -229,18 +229,18 @@
     }
 
     @Override
-    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel) {
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel, double trueLabelProbability) {
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
         switch (left.getKind().getStackKind()) {
             case Int:
             case Long:
             case Object:
-                append(new BranchOp(finalCondition, trueLabel, falseLabel));
+                append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability));
                 break;
             case Float:
             case Double:
-                append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel));
+                append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
@@ -255,22 +255,14 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, boolean negated) {
-        if (negated) {
-            append(new BranchOp(ConditionFlag.NoOverflow, noOverflow, overflow));
-        } else {
-            append(new BranchOp(ConditionFlag.Overflow, overflow, noOverflow));
-        }
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
+        append(new BranchOp(ConditionFlag.Overflow, overflow, noOverflow, overflowProbability));
     }
 
     @Override
-    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef trueDestination, LabelRef falseDestination) {
+    public void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
         emitIntegerTest(left, right);
-        if (negated) {
-            append(new BranchOp(Condition.NE, falseDestination, trueDestination));
-        } else {
-            append(new BranchOp(Condition.EQ, trueDestination, falseDestination));
-        }
+        append(new BranchOp(Condition.EQ, trueDestination, falseDestination, trueDestinationProbability));
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ArgsIntBase.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests codegen for an IJ signature {@code IntStream} instance function.
+ */
+public abstract class ArgsIntBase extends GraalKernelTester {
+
+    static final int NUM = 20;
+
+    @Result public double[] outArray = new double[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = -i;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ArgsIntInstIITest.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests codegen for an II signature {@code IntStream} instance function.
+ */
+public class ArgsIntInstIITest extends ArgsIntBase {
+
+    public void run(int arg1, int arg2, int gid) {
+        outArray[gid] = gid + arg1 + arg2;
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        dispatchMethodKernel(NUM, 7, 6);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ArgsIntInstIJTest.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests codegen for an IJ signature {@code IntStream} instance function.
+ */
+public class ArgsIntInstIJTest extends ArgsIntBase {
+
+    public void run(int arg1, long arg2, int gid) {
+        outArray[gid] = gid + arg1 + arg2;
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        dispatchMethodKernel(NUM, 7, 6);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ArgsIntStatAIITest.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests codegen for an AII signature {@code IntStream} static function.
+ */
+public class ArgsIntStatAIITest extends ArgsIntBase {
+
+    public static void run(double[] out, int arg1, int arg2, int gid) {
+        out[gid] = gid + arg1 + arg2;
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        dispatchMethodKernel(NUM, outArray, 7, 6);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ArgsIntStatAIJTest.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests codegen for an AIJ signature {@code IntStream} static function.
+ */
+public class ArgsIntStatAIJTest extends ArgsIntBase {
+
+    public static void run(double[] out, int arg1, long arg2, int gid) {
+        out[gid] = gid + arg1 + arg2;
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        dispatchMethodKernel(NUM, outArray, 7, 6);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ArgsObjBase.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests codegen for an IJ signature Object stream instance function.
+ */
+public abstract class ArgsObjBase extends GraalKernelTester {
+
+    static class MyObj {
+        public int id;
+        public double d;
+
+        public MyObj(int id) {
+            this.id = id;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof MyObj)) {
+                return false;
+            }
+            MyObj oth = (MyObj) other;
+            return (oth.id == id && oth.d == d);
+        }
+
+        @Override
+        public String toString() {
+            return ("MyObj[" + id + ", " + d + "]");
+        }
+
+        @Override
+        public int hashCode() {
+            return id;
+        }
+
+    }
+
+    static final int NUM = 20;
+
+    @Result public MyObj[] outArray = new MyObj[NUM];
+
+    void setupArrays() {
+        for (int i = 0; i < NUM; i++) {
+            outArray[i] = new MyObj(i + 1);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ArgsObjInstIITest.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests codegen for an II signature Object stream instance function.
+ */
+public class ArgsObjInstIITest extends ArgsObjBase {
+
+    public void run(int arg1, int arg2, MyObj myobj) {
+        myobj.d = myobj.id + arg1 + arg2;
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        dispatchMethodKernel(outArray, 7, 6);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ArgsObjInstIJTest.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests codegen for an IJ signature Object stream instance function.
+ */
+public class ArgsObjInstIJTest extends ArgsObjBase {
+
+    public void run(int arg1, long arg2, MyObj myobj) {
+        myobj.d = myobj.id + arg1 + arg2;
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        dispatchMethodKernel(outArray, 7, 6);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ArgsObjStatIITest.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests codegen for an II signature Object stream static function.
+ */
+public class ArgsObjStatIITest extends ArgsObjBase {
+
+    public static void run(int arg1, int arg2, MyObj myobj) {
+        myobj.d = myobj.id + arg1 + arg2;
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        dispatchMethodKernel(outArray, 7, 6);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ArgsObjStatIJTest.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.*;
+
+/**
+ * Tests codegen for an IJ signature Object stream static function.
+ */
+public class ArgsObjStatIJTest extends ArgsObjBase {
+
+    public static void run(int arg1, long arg2, MyObj myobj) {
+        myobj.d = myobj.id + arg1 + arg2;
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+        dispatchMethodKernel(outArray, 7, 6);
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringEqualsTest.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+import org.junit.Test;
+
+public class StringEqualsTest extends GraalKernelTester {
+
+    static final int NUM = 20;
+    @Result public boolean[] outArray = new boolean[NUM];
+    public String[] inArray = new String[NUM];
+
+    void setupArrays() {
+        char[] chars = new char[100];
+        for (int i = 0; i < chars.length; i++) {
+            chars[i] = (char) ('A' + i);
+        }
+        for (int i = 0; i < NUM; i++) {
+            inArray[i] = new String(chars, 0, 10 + (i % 3));
+        }
+    }
+
+    public void run(String base, int gid) {
+        outArray[gid] = inArray[gid].equals(base);
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        dispatchMethodKernel(NUM, "ABCDEFGHIJ");
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Feb 17 13:48:41 2014 +0100
@@ -189,7 +189,7 @@
     }
 
     @Override
-    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination) {
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
         // We don't have to worry about mirroring the condition on HSAIL.
         Condition finalCondition = cond;
         Variable result = newVariable(left.getKind());
@@ -210,12 +210,12 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, boolean negated) {
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
         throw GraalInternalError.unimplemented();
     }
 
     @Override
-    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef trueDestination, LabelRef falseDestination) {
+    public void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
         throw GraalInternalError.unimplemented();
     }
 
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Feb 17 13:48:41 2014 +0100
@@ -299,7 +299,7 @@
     }
 
     @Override
-    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination) {
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
         switch (left.getKind().getStackKind()) {
             case Int:
                 append(new CompareOp(ICMP, cond, left, right, nextPredRegNum));
@@ -327,12 +327,12 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, boolean negated) {
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
         throw GraalInternalError.unimplemented("PTXLIRGenerator.emitOverflowCheckBranch()");
     }
 
     @Override
-    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef trueDestination, LabelRef falseDestination) {
+    public void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
         // / emitIntegerTest(left, right);
         // append(new BranchOp(negated ? Condition.NE : Condition.EQ, label));
         throw GraalInternalError.unimplemented("emitIntegerTestBranch()");
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Feb 17 13:48:41 2014 +0100
@@ -230,7 +230,7 @@
     }
 
     @Override
-    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination) {
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
         Kind kind = left.getKind().getStackKind();
@@ -254,15 +254,15 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, boolean negated) {
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
         // append(new BranchOp(negated ? ConditionFlag.NoOverflow : ConditionFlag.Overflow, label));
         throw GraalInternalError.unimplemented();
     }
 
     @Override
-    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef trueDestination, LabelRef falseDestination) {
+    public void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
         emitIntegerTest(left, right);
-        append(new BranchOp(negated ? Condition.NE : Condition.EQ, trueDestination, falseDestination, left.getKind().getStackKind()));
+        append(new BranchOp(Condition.EQ, trueDestination, falseDestination, left.getKind().getStackKind()));
     }
 
     private void emitIntegerTest(Value a, Value b) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2013, 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.test.nfi;
+
+import static com.oracle.graal.graph.UnsafeAccess.*;
+import static java.io.File.*;
+import static java.lang.System.*;
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+import java.io.*;
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.runtime.*;
+
+public class NativeFunctionInterfaceTest {
+
+    public final NativeFunctionInterface nfi;
+
+    public NativeFunctionInterfaceTest() {
+        RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class);
+        Assume.assumeTrue(runtimeProvider.getHostBackend() instanceof HostBackend);
+        nfi = ((HostBackend) runtimeProvider.getHostBackend()).getNativeFunctionInterface();
+    }
+
+    private List<Long> allocations = new ArrayList<>();
+
+    protected long malloc(int length) {
+        long buf = unsafe.allocateMemory(length);
+        allocations.add(buf);
+        return buf;
+    }
+
+    @After
+    public void cleanup() {
+        for (long buf : allocations) {
+            unsafe.freeMemory(buf);
+        }
+    }
+
+    private static void assertCStringEquals(long cString, String s) {
+        for (int i = 0; i < s.length(); i++) {
+            assertEquals(unsafe.getByte(cString + i) & 0xFF, (byte) s.charAt(i));
+        }
+        assertEquals(unsafe.getByte(cString + s.length()) & 0xFF, (byte) '\0');
+    }
+
+    @Test
+    public void test1() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        NativeFunctionHandle malloc = nfi.getFunctionHandle("malloc", long.class, int.class);
+        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class);
+        NativeFunctionHandle free = nfi.getFunctionHandle("free", void.class, long.class);
+
+        String string = "GRAAL";
+        int bufferLength = string.length() + 1;
+        long cString = (long) malloc.call(bufferLength);
+        writeCString(string, cString);
+
+        long cStringCopy = malloc(bufferLength);
+        int result = (int) snprintf.call(cStringCopy, bufferLength, cString);
+        Assert.assertEquals(string.length(), result);
+        assertCStringEquals(cString, string);
+        assertCStringEquals(cStringCopy, string);
+
+        free.call(cString);
+    }
+
+    @Test
+    public void test2() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        String formatString = "AB %f%f";
+        long formatCString = writeCString("AB %f%f", malloc(formatString.length() + 1));
+
+        String referenceString = "AB 1.0000001.000000";
+        int bufferLength = referenceString.length() + 1;
+        long buffer = malloc(bufferLength);
+
+        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, double.class, double.class);
+        int result = (int) snprintf.call(buffer, bufferLength, formatCString, 1.0D, 1.0D);
+
+        assertCStringEquals(buffer, referenceString);
+        Assert.assertEquals(referenceString.length(), result);
+    }
+
+    @Test
+    public void test3() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        String format = "%i%i%i%i%i%i%i%i%i%i%i%i";
+        long formatCString = writeCString(format, malloc(format.length() + 1));
+        String referenceString = "01234567891011";
+
+        int bufferLength = referenceString.length() + 1;
+        long buffer = malloc(bufferLength);
+
+        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
+                        int.class, int.class, int.class, int.class, int.class);
+
+        int result = (int) snprintf.call(buffer, bufferLength, formatCString, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+        assertCStringEquals(buffer, referenceString);
+        Assert.assertEquals(referenceString.length(), result);
+    }
+
+    @Test
+    public void test4() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        long str = malloc(49);
+        int[] val = new int[12];
+        for (int i = 0; i < 12; i++) {
+            unsafe.putByte(str + 2 * i, (byte) '%');
+            unsafe.putByte(str + 2 * i + 1, (byte) 'i');
+            val[i] = i;
+        }
+        double[] dval = new double[12];
+        for (int i = 12; i < 24; i++) {
+            unsafe.putByte(str + 2 * i, (byte) '%');
+            unsafe.putByte(str + 2 * i + 1, (byte) 'f');
+            dval[i - 12] = i + 0.5;
+        }
+        unsafe.putByte(str + 48, (byte) '\0');
+
+        String referenceString = "0123456789101112.50000013.50000014.50000015.50000016.50000017.50000018.50000019.50000020.500000" + "21.50000022.50000023.500000";
+        int bufferLength = referenceString.length() + 1;
+
+        long buffer = malloc(bufferLength);
+
+        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
+                        int.class, int.class, int.class, int.class, int.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class,
+                        double.class, double.class, double.class, double.class);
+
+        int result = (int) snprintf.call(buffer, bufferLength, str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], dval[0], dval[1], dval[2],
+                        dval[3], dval[4], dval[5], dval[6], dval[7], dval[8], dval[9], dval[10], dval[11]);
+        assertCStringEquals(buffer, referenceString);
+        Assert.assertEquals(referenceString.length(), result);
+    }
+
+    @Test
+    public void test5() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        long str = malloc(73);
+        int[] val = new int[12];
+        for (int i = 0; i < 12; i++) {
+            unsafe.putByte(str + 2 * i, (byte) '%');
+            unsafe.putByte(str + 2 * i + 1, (byte) 'i');
+            val[i] = i;
+        }
+        double[] dval = new double[12];
+        for (int i = 12; i < 24; i++) {
+            unsafe.putByte(str + 2 * i, (byte) '%');
+            unsafe.putByte(str + 2 * i + 1, (byte) 'f');
+            dval[i - 12] = i + 0.5;
+        }
+        char[] cval = new char[12];
+        for (int i = 24; i < 36; i++) {
+            unsafe.putByte(str + 2 * i, (byte) '%');
+            unsafe.putByte(str + 2 * i + 1, (byte) 'c');
+            cval[i - 24] = (char) ('a' + (i - 24));
+        }
+        unsafe.putByte(str + 72, (byte) '\0');
+
+        String referenceString = "0123456789101112.50000013.50000014.50000015.50000016.50000017.50000018.50000019.50000020.50000021.50000022.50000023.500000abcdefghijkl";
+        int bufferLength = referenceString.length() + 1;
+
+        long buffer = malloc(bufferLength);
+
+        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
+                        int.class, int.class, int.class, int.class, int.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class,
+                        double.class, double.class, double.class, double.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class,
+                        char.class, char.class);
+
+        int result = (int) snprintf.call(buffer, bufferLength, str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], dval[0], dval[1], dval[2],
+                        dval[3], dval[4], dval[5], dval[6], dval[7], dval[8], dval[9], dval[10], dval[11], cval[0], cval[1], cval[2], cval[3], cval[4], cval[5], cval[6], cval[7], cval[8], cval[9],
+                        cval[10], cval[11]);
+        assertCStringEquals(buffer, referenceString);
+        Assert.assertEquals(referenceString.length(), result);
+    }
+
+    @Test
+    public void test6() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        NativeFunctionHandle handle = nfi.getFunctionHandle("pow", double.class, double.class, double.class);
+        double result = (double) handle.call(3D, 5.5D);
+        assertEquals(Math.pow(3D, 5.5D), result, 0);
+    }
+
+    @Test
+    public void test7() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        double result = 0;
+        NativeFunctionHandle handle = nfi.getFunctionHandle("pow", double.class, double.class, double.class);
+        for (int i = 0; i < 10; i++) {
+            result = (double) handle.call(3D, 5.5D);
+        }
+        assertEquals(Math.pow(3D, 5.5D), result, 0);
+    }
+
+    @Test
+    public void test8() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        String formatString = "AB %f%f";
+        long formatCString = writeCString("AB %f%f", malloc(formatString.length() + 1));
+
+        String expected = "AB 1.0000001.000000";
+        int bufferLength = expected.length() + 1;
+        byte[] buffer = new byte[bufferLength];
+
+        NativeFunctionHandle snprintf = nfi.getFunctionHandle("snprintf", int.class, byte[].class, int.class, long.class, double.class, double.class);
+        int result = (int) snprintf.call(buffer, bufferLength, formatCString, 1.0D, 1.0D);
+
+        // trim trailing '\0'
+        String actual = new String(buffer, 0, expected.length());
+
+        assertEquals(expected, actual);
+        Assert.assertEquals(expected.length(), result);
+    }
+
+    private static double[] someDoubles = {2454.346D, 98789.22D, Double.MAX_VALUE, Double.MIN_NORMAL, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY};
+
+    @Test
+    public void test9() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        double[] src = someDoubles.clone();
+        double[] dst = new double[src.length];
+
+        NativeFunctionHandle memcpy = nfi.getFunctionHandle("memcpy", void.class, double[].class, double[].class, int.class);
+        memcpy.call(dst, src, src.length * (Double.SIZE / Byte.SIZE));
+
+        assertArrayEquals(src, dst, 0.0D);
+    }
+
+    private static String getVMName() {
+        String vmName = System.getProperty("java.vm.name").toLowerCase();
+        String vm = null;
+        if (vmName.contains("server")) {
+            vm = "server";
+        } else if (vmName.contains("graal")) {
+            vm = "graal";
+        } else if (vmName.contains("client")) {
+            vm = "client";
+        }
+
+        Assume.assumeTrue(vm != null);
+        return vm;
+    }
+
+    private static String getVMLibPath() {
+        String vm = getVMName();
+
+        String path = String.format("%s%c%s%c%s", getProperty("sun.boot.library.path"), separatorChar, vm, separatorChar, mapLibraryName("jvm"));
+        // Only continue if the library file exists
+        Assume.assumeTrue(new File(path).exists());
+        return path;
+    }
+
+    @Test
+    public void test10() {
+        NativeLibraryHandle vmLib = nfi.getLibraryHandle(getVMLibPath());
+        NativeFunctionHandle currentTimeMillis = nfi.getFunctionHandle(vmLib, "JVM_CurrentTimeMillis", long.class);
+        long time1 = (long) currentTimeMillis.call();
+        long time2 = System.currentTimeMillis();
+        long delta = time2 - time1;
+
+        // The 2 calls to get the current time should not differ by more than
+        // 100 milliseconds at the very most
+        assertTrue(String.valueOf(delta), delta >= 0);
+        assertTrue(String.valueOf(delta), delta < 100);
+    }
+
+    private static String getJavaLibPath() {
+        String path = String.format("%s%c%s", getProperty("sun.boot.library.path"), separatorChar, mapLibraryName("java"));
+        Assume.assumeTrue(new File(path).exists());
+        return path;
+    }
+
+    private static void testD2L(NativeFunctionHandle d2l) {
+        for (double d : someDoubles) {
+            long expected = Double.doubleToRawLongBits(d);
+            long actual = (long) d2l.call(0L, 0L, d);
+            assertEquals(Double.toString(d), expected, actual);
+        }
+    }
+
+    @Test
+    public void test11() {
+        NativeLibraryHandle javaLib = nfi.getLibraryHandle(getJavaLibPath());
+        NativeFunctionHandle d2l = nfi.getFunctionHandle(javaLib, "Java_java_lang_Double_doubleToRawLongBits", long.class, long.class, long.class, double.class);
+        testD2L(d2l);
+    }
+
+    @Test
+    public void test12() {
+        NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())};
+        NativeFunctionHandle d2l = nfi.getFunctionHandle(libs, "Java_java_lang_Double_doubleToRawLongBits", long.class, long.class, long.class, double.class);
+        testD2L(d2l);
+
+        NativeLibraryHandle[] libsReveresed = {libs[1], libs[0]};
+        d2l = nfi.getFunctionHandle(libsReveresed, "Java_java_lang_Double_doubleToRawLongBits", long.class, long.class, long.class, double.class);
+        testD2L(d2l);
+    }
+
+    @Test
+    public void test13() {
+        NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())};
+        NativeFunctionPointer functionPointer = nfi.getFunctionPointer(libs, "Java_java_lang_Double_doubleToRawLongBits");
+        NativeFunctionHandle d2l = nfi.getFunctionHandle(functionPointer, long.class, long.class, long.class, double.class);
+        testD2L(d2l);
+
+        NativeLibraryHandle[] libsReveresed = {libs[1], libs[0]};
+        functionPointer = nfi.getFunctionPointer(libsReveresed, "Java_java_lang_Double_doubleToRawLongBits");
+        d2l = nfi.getFunctionHandle(functionPointer, long.class, long.class, long.class, double.class);
+        testD2L(d2l);
+    }
+
+    @Test
+    public void test14() {
+        if (!nfi.isDefaultLibrarySearchSupported()) {
+            try {
+                nfi.getFunctionHandle("snprintf", int.class);
+                fail();
+            } catch (UnsatisfiedLinkError e) {
+            }
+        }
+    }
+
+    @Test
+    public void test15() {
+        assumeTrue(nfi.isDefaultLibrarySearchSupported());
+        try {
+            nfi.getFunctionHandle("an invalid function name", int.class);
+            fail();
+        } catch (UnsatisfiedLinkError e) {
+        }
+    }
+
+    @Test
+    public void test16() {
+        NativeLibraryHandle javaLib = nfi.getLibraryHandle(getJavaLibPath());
+        try {
+
+            nfi.getFunctionHandle(javaLib, "an invalid function name", int.class);
+            fail();
+        } catch (UnsatisfiedLinkError e) {
+        }
+    }
+
+    @Test
+    public void test17() {
+        NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())};
+        try {
+            nfi.getFunctionPointer(libs, "an invalid function name");
+            fail();
+        } catch (UnsatisfiedLinkError e) {
+        }
+    }
+
+    @Test
+    public void test18() {
+        NativeLibraryHandle[] libs = {nfi.getLibraryHandle(getVMLibPath()), nfi.getLibraryHandle(getJavaLibPath())};
+        try {
+            nfi.getFunctionHandle(libs, "an invalid function name", int.class);
+            fail();
+        } catch (UnsatisfiedLinkError e) {
+        }
+    }
+
+    @Test
+    public void test19() {
+        try {
+            nfi.getLibraryHandle("an invalid library name");
+            fail();
+        } catch (UnsatisfiedLinkError e) {
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Feb 17 13:48:41 2014 +0100
@@ -280,7 +280,9 @@
         try (Scope s = Debug.scope("ControlFlowOptimizations")) {
             EdgeMoveOptimizer.optimize(lir);
             ControlFlowOptimizer.optimize(lir);
-            RedundantMoveElimination.optimize(lir, frameMap, lirGen.getGraph().method());
+            if (lirGen.canEliminateRedundantMoves()) {
+                RedundantMoveElimination.optimize(lir, frameMap, lirGen.getGraph().method());
+            }
             NullCheckOptimizer.optimize(lir, target.implicitNullCheckLimit);
 
             Debug.dump(lir, "After control flow optimization");
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Feb 17 13:48:41 2014 +0100
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.compiler.gen;
 
-import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.api.meta.Value.*;
 import static com.oracle.graal.lir.LIR.*;
@@ -41,7 +40,11 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
+import com.oracle.graal.lir.StandardOp.JumpOp;
+import com.oracle.graal.lir.StandardOp.LabelOp;
+import com.oracle.graal.lir.StandardOp.MoveOp;
+import com.oracle.graal.lir.StandardOp.NoOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
@@ -174,13 +177,7 @@
         this.graph = graph;
         this.providers = providers;
         this.frameMap = frameMap;
-        if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) {
-            this.cc = cc;
-        } else {
-            JavaType[] parameterTypes = new JavaType[]{getMetaAccess().lookupJavaType(long.class)};
-            CallingConvention tmp = frameMap.registerConfig.getCallingConvention(JavaCallee, getMetaAccess().lookupJavaType(void.class), parameterTypes, target(), false);
-            this.cc = new CallingConvention(cc.getStackSize(), cc.getReturn(), tmp.getArgument(0));
-        }
+        this.cc = cc;
         this.nodeOperands = graph.createNodeMap();
         this.lir = lir;
         this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands);
@@ -222,6 +219,14 @@
         return null;
     }
 
+    /**
+     * Returns true if the redundant move elimination optimization should be done after register
+     * allocation.
+     */
+    public boolean canEliminateRedundantMoves() {
+        return true;
+    }
+
     @SuppressWarnings("hiding")
     protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> nodeOperands) {
         return new DebugInfoBuilder(nodeOperands);
@@ -655,37 +660,33 @@
 
     @Override
     public void emitIf(IfNode x) {
-        emitBranch(x.condition(), getLIRBlock(x.trueSuccessor()), getLIRBlock(x.falseSuccessor()));
+        emitBranch(x.condition(), getLIRBlock(x.trueSuccessor()), getLIRBlock(x.falseSuccessor()), x.probability(x.trueSuccessor()));
     }
 
-    public void emitBranch(LogicNode node, LabelRef trueSuccessor, LabelRef falseSuccessor) {
+    public void emitBranch(LogicNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
         if (node instanceof IsNullNode) {
-            emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor);
+            emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability);
         } else if (node instanceof CompareNode) {
-            emitCompareBranch((CompareNode) node, trueSuccessor, falseSuccessor);
+            emitCompareBranch((CompareNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability);
         } else if (node instanceof LogicConstantNode) {
             emitConstantBranch(((LogicConstantNode) node).getValue(), trueSuccessor, falseSuccessor);
         } else if (node instanceof IntegerTestNode) {
-            emitIntegerTestBranch((IntegerTestNode) node, trueSuccessor, falseSuccessor);
+            emitIntegerTestBranch((IntegerTestNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability);
         } else {
             throw GraalInternalError.unimplemented(node.toString());
         }
     }
 
-    private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor) {
-        emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, falseSuccessor);
+    private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
+        emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, falseSuccessor, trueSuccessorProbability);
     }
 
-    public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessor, LabelRef falseSuccessor) {
-        emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor);
+    public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
+        emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor, trueSuccessorProbability);
     }
 
-    public void emitOverflowCheckBranch(LabelRef noOverflowBlock, LabelRef overflowBlock) {
-        emitOverflowCheckBranch(overflowBlock, noOverflowBlock, false);
-    }
-
-    public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessor, LabelRef falseSuccessor) {
-        emitIntegerTestBranch(operand(test.x()), operand(test.y()), false, trueSuccessor, falseSuccessor);
+    public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
+        emitIntegerTestBranch(operand(test.x()), operand(test.y()), trueSuccessor, falseSuccessor, trueSuccessorProbability);
     }
 
     public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) {
@@ -719,11 +720,11 @@
 
     public abstract void emitJump(LabelRef label);
 
-    public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination);
+    public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability);
 
-    public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, boolean negated);
+    public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability);
 
-    public abstract void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef trueDestination, LabelRef falseDestination);
+    public abstract void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability);
 
     public abstract Variable emitConditionalMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
 
@@ -851,7 +852,8 @@
             Variable value = load(operand(x.value()));
             if (keyCount == 1) {
                 assert defaultTarget != null;
-                emitCompareBranch(load(operand(x.value())), x.keyAt(0), Condition.EQ, false, getLIRBlock(x.keySuccessor(0)), defaultTarget);
+                double probability = x.probability(x.keySuccessor(0));
+                emitCompareBranch(load(operand(x.value())), x.keyAt(0), Condition.EQ, false, getLIRBlock(x.keySuccessor(0)), defaultTarget, probability);
             } else {
                 LabelRef[] keyTargets = new LabelRef[keyCount];
                 Constant[] keyConstants = new Constant[keyCount];
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/UnsafeAccess.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/UnsafeAccess.java	Mon Feb 17 13:48:41 2014 +0100
@@ -49,4 +49,33 @@
             throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
         }
     }
+
+    /**
+     * Copies the contents of a {@link String} to a native memory buffer as a {@code '\0'}
+     * terminated C string. The native memory buffer is allocated via
+     * {@link Unsafe#allocateMemory(long)}. The caller is responsible for releasing the buffer when
+     * it is no longer needed via {@link Unsafe#freeMemory(long)}.
+     * 
+     * @return the native memory pointer of the C string created from {@code s}
+     */
+    public static long createCString(String s) {
+        return writeCString(s, unsafe.allocateMemory(s.length() + 1));
+    }
+
+    /**
+     * Writes the contents of a {@link String} to a native memory buffer as a {@code '\0'}
+     * terminated C string. The caller is responsible for ensuring the buffer is at least
+     * {@code s.length() + 1} bytes long. The caller is also responsible for releasing the buffer
+     * when it is no longer.
+     * 
+     * @return the value of {@code buf}
+     */
+    public static long writeCString(String s, long buf) {
+        int size = s.length();
+        for (int i = 0; i < size; i++) {
+            unsafe.putByte(buf + i, (byte) s.charAt(i));
+        }
+        unsafe.putByte(buf + size, (byte) '\0');
+        return buf;
+    }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Mon Feb 17 13:48:41 2014 +0100
@@ -40,15 +40,14 @@
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nfi.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nfi.hotspot.amd64.*;
 import com.oracle.graal.nodes.*;
 
 /**
@@ -311,12 +310,12 @@
 
     @Override
     public NativeFunctionInterface getNativeFunctionInterface() {
-        AMD64HotSpotNativeFunctionPointer libraryLoadPointer = new AMD64HotSpotNativeFunctionPointer(getRuntime().getConfig().libraryLoadAddress, "GNFI_UTIL_LOADLIBRARY");
-        AMD64HotSpotNativeFunctionPointer functionLookupPointer = new AMD64HotSpotNativeFunctionPointer(getRuntime().getConfig().functionLookupAddress, "GNFI_UTIL_FUNCTIONLOOKUP");
-        AMD64HotSpotNativeLibraryHandle rtldDefault = new AMD64HotSpotNativeLibraryHandle(getRuntime().getConfig().rtldDefault);
-        if (!libraryLoadPointer.isValid() || !functionLookupPointer.isValid()) {
-            throw GraalInternalError.shouldNotReachHere("Lookup Pointers null");
-        }
-        return new AMD64HotSpotNativeFunctionInterface(this.getProviders(), this, libraryLoadPointer, functionLookupPointer, rtldDefault);
+        HotSpotVMConfig config = getRuntime().getConfig();
+        RawNativeCallNodeFactory factory = new RawNativeCallNodeFactory() {
+            public FixedWithNextNode createRawCallNode(Kind returnType, Constant functionPointer, ValueNode... args) {
+                return new AMD64RawNativeCallNode(returnType, functionPointer, args);
+            }
+        };
+        return new HotSpotNativeFunctionInterface(getProviders(), factory, this, config.dllLoad, config.dllLookup, config.rtldDefault);
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Feb 17 13:48:41 2014 +0100
@@ -158,7 +158,6 @@
 
         CallingConvention incomingArguments = cc;
 
-        RegisterValue rbpParam = rbp.asValue(Kind.Long);
         Value[] params = new Value[incomingArguments.getArgumentCount() + 1];
         for (int i = 0; i < params.length - 1; i++) {
             params[i] = toStackKind(incomingArguments.getArgument(i));
@@ -169,7 +168,7 @@
                 }
             }
         }
-        params[params.length - 1] = rbpParam;
+        params[params.length - 1] = rbp.asValue(Kind.Long);
 
         emitIncomingValues(params);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014, 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.amd64;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.amd64.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+public class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRGenLowerable {
+
+    private final Constant functionPointer;
+    @Input private final NodeInputList<ValueNode> args;
+
+    public AMD64RawNativeCallNode(Kind returnType, Constant functionPointer, ValueNode[] args) {
+        super(StampFactory.forKind(returnType));
+        this.functionPointer = functionPointer;
+        this.args = new NodeInputList<>(this, args);
+    }
+
+    @Override
+    public void generate(LIRGenerator generator) {
+        AMD64LIRGenerator gen = (AMD64LIRGenerator) generator;
+        Value[] parameter = new Value[args.count()];
+        JavaType[] parameterTypes = new JavaType[args.count()];
+        for (int i = 0; i < args.count(); i++) {
+            parameter[i] = generator.operand(args.get(i));
+            parameterTypes[i] = args.get(i).stamp().javaType(gen.getMetaAccess());
+        }
+        ResolvedJavaType returnType = stamp().javaType(gen.getMetaAccess());
+        CallingConvention cc = generator.getCodeCache().getRegisterConfig().getCallingConvention(Type.NativeCall, returnType, parameterTypes, generator.target(), false);
+        gen.emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args));
+        if (this.kind() != Kind.Void) {
+            generator.setResult(this, gen.emitMove(cc.getReturn()));
+        }
+    }
+
+    private static int countFloatingTypeArguments(NodeInputList<ValueNode> args) {
+        int count = 0;
+        for (ValueNode n : args) {
+            if (n.kind() == Kind.Double || n.kind() == Kind.Float) {
+                count++;
+            }
+        }
+        if (count > 8) {
+            return 8;
+        }
+        return count;
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java	Mon Feb 17 13:48:41 2014 +0100
@@ -26,7 +26,6 @@
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.lang.reflect.*;
-import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -63,7 +62,7 @@
     private static HotSpotNmethod getCompiledLambda(Class intConsumerClass) {
         Method acceptMethod = null;
         for (Method m : intConsumerClass.getMethods()) {
-            if (m.getName().equals("accept") && Arrays.equals(new Class[]{int.class}, m.getParameterTypes())) {
+            if (m.getName().equals("accept")) {
                 assert acceptMethod == null : "found more than one implementation of accept(int) in " + intConsumerClass;
                 acceptMethod = m;
             }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Mon Feb 17 13:48:41 2014 +0100
@@ -48,11 +48,9 @@
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.hsail.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
-import com.oracle.graal.replacements.hsail.*;
 
 /**
  * HSAIL specific backend.
@@ -107,10 +105,8 @@
         lowerer.initialize(providers, config);
 
         // Register the replacements used by the HSAIL backend.
-        Replacements replacements = providers.getReplacements();
-
-        // Register the substitutions for java.lang.Math routines.
-        replacements.registerSubstitutions(HSAILMathSubstitutions.class);
+        HSAILHotSpotReplacementsImpl replacements = (HSAILHotSpotReplacementsImpl) providers.getReplacements();
+        replacements.completeInitialization();
     }
 
     /**
@@ -321,7 +317,7 @@
         }
         // Emit the kernel function parameters.
         for (int i = 0; i < totalParamCount; i++) {
-            String str = "kernarg_" + paramHsailSizes[i] + " " + paramNames[i];
+            String str = "align 8 kernarg_" + paramHsailSizes[i] + " " + paramNames[i];
 
             if (i != totalParamCount - 1) {
                 str += ",";
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotReplacementsImpl.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotReplacementsImpl.java	Mon Feb 17 13:48:41 2014 +0100
@@ -30,6 +30,8 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.hsail.*;
+import java.util.HashSet;
 
 /**
  * The substitutions and snippets supported by HSAIL.
@@ -37,12 +39,31 @@
 public class HSAILHotSpotReplacementsImpl extends ReplacementsImpl {
 
     private final Replacements host;
+    private HashSet<ResolvedJavaMethod> ignoredResolvedMethods = new HashSet<>();
 
     public HSAILHotSpotReplacementsImpl(Providers providers, Assumptions assumptions, TargetDescription target, Replacements host) {
         super(providers, assumptions, target);
         this.host = host;
     }
 
+    public void addIgnoredResolvedMethod(Class<?> cls, String methName, Class<?>... params) {
+        try {
+            Method m = cls.getMethod(methName, params);
+            ResolvedJavaMethod rjm = providers.getMetaAccess().lookupJavaMethod(m);
+            ignoredResolvedMethods.add(rjm);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void completeInitialization() {
+        // Register the substitutions for java.lang.Math routines.
+        registerSubstitutions(HSAILMathSubstitutions.class);
+
+        // Register the ignored substitutions
+        addIgnoredResolvedMethod(String.class, "equals", Object.class);
+    }
+
     @Override
     protected ResolvedJavaMethod registerMethodSubstitution(Member originalMethod, Method substituteMethod) {
         // TODO: decide if we want to override this in any way
@@ -70,9 +91,13 @@
     public StructuredGraph getMethodSubstitution(ResolvedJavaMethod original) {
         StructuredGraph m = super.getMethodSubstitution(original);
         if (m == null) {
-            // eventually we want to only defer certain substitutions to the host, but for now we
-            // will defer everything
-            return host.getMethodSubstitution(original);
+            // we check for a few special cases we do NOT want to defer here
+            // but basically we defer everything else to the host
+            if (ignoredResolvedMethods.contains(original)) {
+                return null;
+            } else {
+                return host.getMethodSubstitution(original);
+            }
         }
         return m;
     }
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Mon Feb 17 13:48:41 2014 +0100
@@ -137,9 +137,18 @@
             long launchKernel = getLaunchKernelAddress();
             hostForeignCalls.linkForeignCall(hostProviders, CALL_KERNEL, launchKernel, false, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
         }
+        /* Add a shutdown hook to destroy CUDA context(s) */
+        Runtime.getRuntime().addShutdownHook(new Thread("PTXShutdown") {
+            @Override
+            public void run() {
+                destroyContext();
+            }
+        });
         super.completeInitialization();
     }
 
+    private static native void destroyContext();
+
     /**
      * Gets the address of {@code Ptx::execute_kernel_from_vm()}.
      */
@@ -365,7 +374,7 @@
 
     @Override
     public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir) {
-        return new PTXLIRGenerator(graph, getProviders(), frameMap, cc, lir);
+        return new PTXHotSpotLIRGenerator(graph, getProviders(), getRuntime().getConfig(), frameMap, cc, lir);
     }
 
     private static void emitKernelEntry(CompilationResultBuilder crb, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2014, 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.ptx;
+
+import com.oracle.graal.api.code.CallingConvention;
+import com.oracle.graal.api.code.StackSlot;
+import com.oracle.graal.api.meta.DeoptimizationAction;
+import com.oracle.graal.api.meta.DeoptimizationReason;
+import com.oracle.graal.api.meta.Value;
+import com.oracle.graal.compiler.ptx.PTXLIRGenerator;
+import com.oracle.graal.graph.GraalInternalError;
+import com.oracle.graal.hotspot.HotSpotLIRGenerator;
+import com.oracle.graal.hotspot.HotSpotVMConfig;
+import com.oracle.graal.hotspot.meta.HotSpotProviders;
+import com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode;
+import com.oracle.graal.lir.FrameMap;
+import com.oracle.graal.lir.LIR;
+import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.ValueNode;
+
+/**
+ * LIR generator specialized for PTX HotSpot.
+ */
+public class PTXHotSpotLIRGenerator extends PTXLIRGenerator implements HotSpotLIRGenerator {
+
+    protected PTXHotSpotLIRGenerator(StructuredGraph graph, HotSpotProviders providers, HotSpotVMConfig config, FrameMap frameMap, CallingConvention cc, LIR lir) {
+        super(graph, providers, frameMap, cc, lir);
+        assert config.basicLockSize == 8;
+    }
+
+    public void emitPrefetchAllocate(ValueNode address, ValueNode distance) {
+        // nop
+    }
+
+    public void emitTailcall(Value[] args, Value address) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitPatchReturnAddress(ValueNode address) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    public StackSlot getLockSlot(int lockDepth) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
+    public HotSpotProviders getProviders() {
+        throw GraalInternalError.unimplemented();
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Feb 17 13:48:41 2014 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot;
 
+import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.compiler.GraalCompiler.*;
 import static com.oracle.graal.hotspot.bridge.VMToCompilerImpl.*;
@@ -222,6 +223,13 @@
                 }
                 InlinedBytecodes.add(method.getCodeSize());
                 CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
+                if (graph.getEntryBCI() != StructuredGraph.INVOCATION_ENTRY_BCI) {
+                    // for OSR, only a pointer is passed to the method.
+                    JavaType[] parameterTypes = new JavaType[]{providers.getMetaAccess().lookupJavaType(long.class)};
+                    CallingConvention tmp = providers.getCodeCache().getRegisterConfig().getCallingConvention(JavaCallee, providers.getMetaAccess().lookupJavaType(void.class), parameterTypes,
+                                    backend.getTarget(), false);
+                    cc = new CallingConvention(cc.getStackSize(), cc.getReturn(), tmp.getArgument(0));
+                }
                 Suites suites = getSuites(providers);
                 ProfilingInfo profilingInfo = getProfilingInfo();
                 OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Mon Feb 17 13:48:41 2014 +0100
@@ -56,6 +56,7 @@
         ValueNode lock = state.lockAt(lockIndex);
         Value object = toValue(lock);
         boolean eliminated = object instanceof VirtualObject && state.monitorIdAt(lockIndex) != null;
+        assert state.monitorIdAt(lockIndex) == null || state.monitorIdAt(lockIndex).getLockDepth() == lockDepth;
         return new HotSpotMonitorValue(object, slot, eliminated);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Mon Feb 17 13:48:41 2014 +0100
@@ -840,14 +840,35 @@
     @HotSpotVMField(name = "JavaThread::_vm_result", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int threadObjectResultOffset;
     @HotSpotVMField(name = "JavaThread::_graal_counters[0]", type = "jlong", get = HotSpotVMField.Type.OFFSET, optional = true) @Stable public int graalCountersThreadOffset;
 
-    // The native side (graalCompilerToVM.cpp) sets the rtldDefault if the
-    // platform is NOT Windows (Windows is currently not supported).
-    // AMD64NativeFunctionInterface checks if rtld_default handle is valid.
-    // Using 0 is not possible as it is a valid value for rtldDefault on some platforms.
+    /**
+     * An invalid value for {@link #rtldDefault}.
+     */
     public static final long INVALID_RTLD_DEFAULT_HANDLE = 0xDEADFACE;
 
-    @Stable public long libraryLoadAddress;
-    @Stable public long functionLookupAddress;
+    /**
+     * Address of the library lookup routine. The C signature of this routine is:
+     * 
+     * <pre>
+     *     void* (const char *filename, char *ebuf, int ebuflen)
+     * </pre>
+     */
+    @Stable public long dllLoad;
+
+    /**
+     * Address of the library lookup routine. The C signature of this routine is:
+     * 
+     * <pre>
+     *     void* (void* handle, const char* name)
+     * </pre>
+     */
+    @Stable public long dllLookup;
+
+    /**
+     * A pseudo-handle which when used as the first argument to {@link #dllLookup} means lookup will
+     * return the first occurrence of the desired symbol using the default library search order. If
+     * this field is {@value #INVALID_RTLD_DEFAULT_HANDLE}, then this capability is not supported on
+     * the current platform.
+     */
     @Stable public long rtldDefault = INVALID_RTLD_DEFAULT_HANDLE;
 
     /**
@@ -1005,6 +1026,8 @@
     @HotSpotVMConstant(name = "JVM_CONSTANT_MethodType") @Stable public int jvmConstantMethodType;
     @HotSpotVMConstant(name = "JVM_CONSTANT_MethodTypeInError") @Stable public int jvmConstantMethodTypeInError;
 
+    @HotSpotVMConstant(name = "HeapWordSize") @Stable public int heapWordSize;
+
     @HotSpotVMField(name = "Symbol::_length", type = "unsigned short", get = HotSpotVMField.Type.OFFSET) @Stable public int symbolLengthOffset;
     @HotSpotVMField(name = "Symbol::_body[0]", type = "jbyte", get = HotSpotVMField.Type.OFFSET) @Stable public int symbolBodyOffset;
 
@@ -1261,6 +1284,35 @@
     @HotSpotVMField(name = "StubRoutines::_updateBytesCRC32", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long updateBytesCRC32Stub;
     @HotSpotVMField(name = "StubRoutines::_crc_table_adr", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long crcTableAddress;
 
+    @HotSpotVMField(name = "StubRoutines::_jbyte_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jbyteArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_jshort_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jshortArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_jint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jintArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_jlong_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jlongArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_oop_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_oop_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopArraycopyUninit;
+    @HotSpotVMField(name = "StubRoutines::_jbyte_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jbyteDisjointArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_jshort_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jshortDisjointArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_jint_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jintDisjointArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_jlong_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jlongDisjointArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_oop_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopDisjointArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_oop_disjoint_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopDisjointArraycopyUninit;
+    @HotSpotVMField(name = "StubRoutines::_arrayof_jbyte_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jbyteAlignedArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_arrayof_jshort_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jshortAlignedArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_arrayof_jint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jintAlignedArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_arrayof_jlong_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jlongAlignedArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_arrayof_oop_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long alignedOopAlignedArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_arrayof_oop_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long alignedOopArraycopyUninit;
+    @HotSpotVMField(name = "StubRoutines::_arrayof_jbyte_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jbyteAlignedDisjointArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_arrayof_jshort_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jshortAlignedDisjointArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_arrayof_jint_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jintAlignedDisjointArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_arrayof_jlong_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jlongAlignedDisjointArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_arrayof_oop_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long alignedOopDisjointArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long alignedOopDisjointArraycopyUninit;
+    @HotSpotVMField(name = "StubRoutines::_checkcast_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long checkcastArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_checkcast_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long checkcastArraycopyUninit;
+    @HotSpotVMField(name = "StubRoutines::_unsafe_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long unsafeArraycopy;
+    @HotSpotVMField(name = "StubRoutines::_generic_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long genericArraycopy;
+
     @Stable public long newInstanceAddress;
     @Stable public long newArrayAddress;
     @Stable public long newMultiArrayAddress;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Mon Feb 17 13:48:41 2014 +0100
@@ -54,20 +54,30 @@
     boolean hasBalancedMonitors(long metaspaceMethod);
 
     /**
-     * Determines if a given metaspace Method object is compilable. A method may not be compilable
-     * for a number of reasons such as:
+     * Determines if a given metaspace Method can be inlined. A method may not be inlinable for a
+     * number of reasons such as:
      * <ul>
-     * <li>a CompileOracle directive may prevent compilation of methods</li>
+     * <li>a CompileOracle directive may prevent inlining or compilation of this methods</li>
      * <li>the method may have a bytecode breakpoint set</li>
      * <li>the method may have other bytecode features that require special handling by the VM</li>
      * </ul>
      * 
-     * A non-compilable method should not be inlined.
+     * @param metaspaceMethod the metaspace Method object to query
+     * @return true if the method can be inlined
+     */
+    boolean canInlineMethod(long metaspaceMethod);
+
+    /**
+     * Determines if a given metaspace Method should be inlined at any cost. This could be because:
+     * <ul>
+     * <li>a CompileOracle directive may forces inlining of this methods</li>
+     * <li>an annotation forces inlining of this method</li>
+     * </ul>
      * 
      * @param metaspaceMethod the metaspace Method object to query
-     * @return true if the method is compilable
+     * @return true if the method should be inlined
      */
-    boolean isMethodCompilable(long metaspaceMethod);
+    boolean shouldInlineMethod(long metaspaceMethod);
 
     /**
      * Used to implement {@link ResolvedJavaType#findUniqueConcreteMethod(ResolvedJavaMethod)}.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Mon Feb 17 13:48:41 2014 +0100
@@ -53,9 +53,6 @@
     public native boolean hasBalancedMonitors(long metaspaceMethod);
 
     @Override
-    public native boolean isMethodCompilable(long metaspaceMethod);
-
-    @Override
     public native long findUniqueConcreteMethod(long metaspaceMethod);
 
     @Override
@@ -174,4 +171,8 @@
     public native int allocateCompileId(HotSpotResolvedJavaMethod method, int entryBCI);
 
     public native String getGPUs();
+
+    public native boolean canInlineMethod(long metaspaceMethod);
+
+    public native boolean shouldInlineMethod(long metaspaceMethod);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Mon Feb 17 13:48:41 2014 +0100
@@ -51,6 +51,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.hotspot.stubs.*;
 
 /**
@@ -66,6 +67,14 @@
         stub.getLinkage().setCompiledStub(stub);
     }
 
+    private void registerArrayCopy(Kind kind, long routine, long alignedRoutine, long disjointRoutine, long alignedDisjointRoutine) {
+        LocationIdentity killed = NamedLocationIdentity.getArrayLocation(kind);
+        registerForeignCall(ArrayCopySnippets.lookupArraycopyDescriptor(kind, false, false), routine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed);
+        registerForeignCall(ArrayCopySnippets.lookupArraycopyDescriptor(kind, true, false), alignedRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed);
+        registerForeignCall(ArrayCopySnippets.lookupArraycopyDescriptor(kind, false, true), disjointRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed);
+        registerForeignCall(ArrayCopySnippets.lookupArraycopyDescriptor(kind, true, true), alignedDisjointRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed);
+    }
+
     public void initialize(HotSpotProviders providers, HotSpotVMConfig c) {
         TargetDescription target = providers.getCodeCache().getTarget();
 
@@ -110,5 +119,15 @@
         linkForeignCall(providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
+
+        registerArrayCopy(Kind.Byte, c.jbyteArraycopy, c.jbyteAlignedArraycopy, c.jbyteDisjointArraycopy, c.jbyteAlignedDisjointArraycopy);
+        registerArrayCopy(Kind.Boolean, c.jbyteArraycopy, c.jbyteAlignedArraycopy, c.jbyteDisjointArraycopy, c.jbyteAlignedDisjointArraycopy);
+        registerArrayCopy(Kind.Char, c.jshortArraycopy, c.jshortAlignedArraycopy, c.jshortDisjointArraycopy, c.jshortAlignedDisjointArraycopy);
+        registerArrayCopy(Kind.Short, c.jshortArraycopy, c.jshortAlignedArraycopy, c.jshortDisjointArraycopy, c.jshortAlignedDisjointArraycopy);
+        registerArrayCopy(Kind.Int, c.jintArraycopy, c.jintAlignedArraycopy, c.jintDisjointArraycopy, c.jintAlignedDisjointArraycopy);
+        registerArrayCopy(Kind.Float, c.jintArraycopy, c.jintAlignedArraycopy, c.jintDisjointArraycopy, c.jintAlignedDisjointArraycopy);
+        registerArrayCopy(Kind.Long, c.jlongArraycopy, c.jlongAlignedArraycopy, c.jlongDisjointArraycopy, c.jlongAlignedDisjointArraycopy);
+        registerArrayCopy(Kind.Double, c.jlongArraycopy, c.jlongAlignedArraycopy, c.jlongDisjointArraycopy, c.jlongAlignedDisjointArraycopy);
+
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Mon Feb 17 13:48:41 2014 +0100
@@ -245,27 +245,9 @@
     }
 
     /**
-     * Returns true if this method has a ForceInline annotation.
-     * 
-     * @return true if ForceInline annotation present, false otherwise
-     */
-    public boolean isForceInline() {
-        return forceInline;
-    }
-
-    /**
-     * Returns true if this method has a DontInline annotation.
-     * 
-     * @return true if DontInline annotation present, false otherwise
-     */
-    public boolean isDontInline() {
-        return dontInline;
-    }
-
-    /**
      * Manually adds a DontInline annotation to this method.
      */
-    public void setDontInline() {
+    public void setNotInlineable() {
         dontInline = true;
         runtime().getCompilerToVM().doNotInlineOrCompile(metaspaceMethod);
     }
@@ -488,7 +470,15 @@
         if (dontInline) {
             return false;
         }
-        return runtime().getCompilerToVM().isMethodCompilable(metaspaceMethod);
+        return runtime().getCompilerToVM().canInlineMethod(metaspaceMethod);
+    }
+
+    @Override
+    public boolean shouldBeInlined() {
+        if (forceInline) {
+            return true;
+        }
+        return runtime().getCompilerToVM().shouldInlineMethod(metaspaceMethod);
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2014, 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.nfi;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.Debug.Scope;
+import com.oracle.graal.graph.*;
+
+public class HotSpotNativeFunctionHandle implements NativeFunctionHandle {
+
+    private final InstalledCode code;
+    private final String name;
+    private final Class[] argumentTypes;
+
+    public HotSpotNativeFunctionHandle(InstalledCode code, String name, Class... argumentTypes) {
+        this.argumentTypes = argumentTypes;
+        this.name = name;
+        this.code = code;
+    }
+
+    private void traceCall(Object... args) {
+        try (Scope s = Debug.scope("GNFI")) {
+            if (Debug.isLogEnabled()) {
+                Debug.log("[GNFI] %s%s", name, Arrays.toString(args));
+            }
+        }
+    }
+
+    private void traceResult(Object result) {
+        try (Scope s = Debug.scope("GNFI")) {
+            if (Debug.isLogEnabled()) {
+                Debug.log("[GNFI] %s --> %s", name, result);
+            }
+        }
+    }
+
+    @Override
+    public Object call(Object... args) {
+        assert checkArgs(args);
+        try {
+            traceCall(args);
+            Object res = code.execute(args, null, null);
+            traceResult(res);
+            return res;
+        } catch (InvalidInstalledCodeException e) {
+            throw GraalInternalError.shouldNotReachHere("Execution of GNFI Callstub failed: " + name);
+        }
+    }
+
+    private boolean checkArgs(Object... args) {
+        assert args.length == argumentTypes.length : this + " expected " + argumentTypes.length + " args, got " + args.length;
+        for (int i = 0; i < argumentTypes.length; i++) {
+            Object arg = args[i];
+            assert arg != null;
+            Class expectedType = argumentTypes[i];
+            if (expectedType.isPrimitive()) {
+                Kind kind = Kind.fromJavaClass(expectedType);
+                expectedType = kind.toBoxedJavaClass();
+            }
+            assert expectedType == arg.getClass() : this + " expected arg " + i + " to be " + expectedType.getName() + ", not " + arg.getClass().getName();
+
+        }
+        return true;
+    }
+
+    public InstalledCode getCallStub() {
+        return code;
+    }
+
+    @Override
+    public String toString() {
+        return name + Arrays.toString(argumentTypes);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2014, 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.nfi;
+
+import static com.oracle.graal.api.code.CodeUtil.*;
+import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.hotspot.nfi.NativeCallStubGraphBuilder.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.Debug.Scope;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class HotSpotNativeFunctionInterface implements NativeFunctionInterface {
+
+    private final HotSpotProviders providers;
+    private final Backend backend;
+    private final HotSpotNativeLibraryHandle rtldDefault;
+    private final HotSpotNativeFunctionPointer libraryLoadFunctionPointer;
+    private final HotSpotNativeFunctionPointer functionLookupFunctionPointer;
+    private final RawNativeCallNodeFactory factory;
+
+    private HotSpotNativeFunctionHandle libraryLookupFunctionHandle;
+    private HotSpotNativeFunctionHandle dllLookupFunctionHandle;
+
+    public HotSpotNativeFunctionInterface(HotSpotProviders providers, RawNativeCallNodeFactory factory, Backend backend, long dlopen, long dlsym, long rtldDefault) {
+        this.rtldDefault = rtldDefault == HotSpotVMConfig.INVALID_RTLD_DEFAULT_HANDLE ? null : new HotSpotNativeLibraryHandle("RTLD_DEFAULT", rtldDefault);
+        this.providers = providers;
+        this.backend = backend;
+        this.factory = factory;
+        this.libraryLoadFunctionPointer = new HotSpotNativeFunctionPointer(dlopen, "os::dll_load");
+        this.functionLookupFunctionPointer = new HotSpotNativeFunctionPointer(dlsym, "os::dll_lookup");
+    }
+
+    @Override
+    public HotSpotNativeLibraryHandle getLibraryHandle(String libPath) {
+        if (libraryLookupFunctionHandle == null) {
+            libraryLookupFunctionHandle = createHandle(libraryLoadFunctionPointer, long.class, long.class, long.class, int.class);
+        }
+
+        int ebufLen = 1024;
+        // Allocating a single chunk for both the error message buffer and the
+        // file name simplifies deallocation below.
+        long buffer = unsafe.allocateMemory(ebufLen + libPath.length() + 1);
+        long ebuf = buffer;
+        long libPathCString = writeCString(libPath, buffer + ebufLen);
+        try {
+            long handle = (long) libraryLookupFunctionHandle.call(libPathCString, ebuf, ebufLen);
+            if (handle == 0) {
+                throw new UnsatisfiedLinkError(libPath);
+            }
+            return new HotSpotNativeLibraryHandle(libPath, handle);
+        } finally {
+            unsafe.freeMemory(buffer);
+        }
+    }
+
+    @Override
+    public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class returnType, Class... argumentTypes) {
+        HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, library, true);
+        return createHandle(functionPointer, returnType, argumentTypes);
+    }
+
+    @Override
+    public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class returnType, Class... argumentTypes) {
+        HotSpotNativeFunctionPointer functionPointer = null;
+        for (NativeLibraryHandle libraryHandle : libraries) {
+            functionPointer = lookupFunctionPointer(name, libraryHandle, false);
+            if (functionPointer != null) {
+                return createHandle(functionPointer, returnType, argumentTypes);
+            }
+        }
+        // Fall back to default library path
+        return getFunctionHandle(name, returnType, argumentTypes);
+    }
+
+    @Override
+    public HotSpotNativeFunctionHandle getFunctionHandle(String name, Class returnType, Class... argumentTypes) {
+        if (rtldDefault == null) {
+            throw new UnsatisfiedLinkError(name);
+        }
+        return getFunctionHandle(rtldDefault, name, returnType, argumentTypes);
+    }
+
+    private HotSpotNativeFunctionPointer lookupFunctionPointer(String name, NativeLibraryHandle library, boolean linkageErrorIfMissing) {
+        if (name == null || library == null) {
+            throw new NullPointerException();
+        }
+
+        if (dllLookupFunctionHandle == null) {
+            dllLookupFunctionHandle = createHandle(functionLookupFunctionPointer, long.class, long.class, long.class);
+        }
+        long nameCString = createCString(name);
+        try {
+            long functionPointer = (long) dllLookupFunctionHandle.call(((HotSpotNativeLibraryHandle) library).value, nameCString);
+            if (functionPointer == 0L) {
+                if (!linkageErrorIfMissing) {
+                    return null;
+                }
+                throw new UnsatisfiedLinkError(name);
+            }
+            return new HotSpotNativeFunctionPointer(functionPointer, name);
+        } finally {
+            unsafe.freeMemory(nameCString);
+        }
+    }
+
+    @Override
+    public HotSpotNativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes) {
+        if (!(functionPointer instanceof HotSpotNativeFunctionPointer)) {
+            throw new UnsatisfiedLinkError(functionPointer.getName());
+        }
+        return createHandle(functionPointer, returnType, argumentTypes);
+    }
+
+    private HotSpotNativeFunctionHandle createHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes) {
+        HotSpotNativeFunctionPointer hs = (HotSpotNativeFunctionPointer) functionPointer;
+        InstalledCode code = installNativeFunctionStub(hs.value, returnType, argumentTypes);
+        return new HotSpotNativeFunctionHandle(code, hs.name, argumentTypes);
+    }
+
+    /**
+     * Creates and installs a stub for calling a native function.
+     */
+    private InstalledCode installNativeFunctionStub(long functionPointer, Class returnType, Class... argumentTypes) {
+        StructuredGraph g = getGraph(providers, factory, functionPointer, returnType, argumentTypes);
+        Suites suites = providers.getSuites().createSuites();
+        PhaseSuite<HighTierContext> phaseSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy();
+        CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, g.method(), false);
+        CompilationResult compResult = GraalCompiler.compileGraph(g, cc, g.method(), providers, backend, backend.getTarget(), null, phaseSuite, OptimisticOptimizations.ALL,
+                        DefaultProfilingInfo.get(TriState.UNKNOWN), null, suites, true, new CompilationResult(), CompilationResultBuilderFactory.Default);
+        InstalledCode installedCode;
+        try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache(), g.method())) {
+            installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null);
+        }
+        return installedCode;
+    }
+
+    @Override
+    public HotSpotNativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraries, String name) {
+        for (NativeLibraryHandle libraryHandle : libraries) {
+            HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, libraryHandle, false);
+            if (functionPointer != null) {
+                return functionPointer;
+            }
+        }
+        // Fall back to default library path
+        if (rtldDefault == null) {
+            throw new UnsatisfiedLinkError(name);
+        }
+        return lookupFunctionPointer(name, rtldDefault, true);
+    }
+
+    public boolean isDefaultLibrarySearchSupported() {
+        return rtldDefault != null;
+    }
+
+    @Override
+    public NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue) {
+        return new HotSpotNativeFunctionPointer(rawValue, null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionPointer.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 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.nfi;
+
+import com.oracle.graal.api.code.*;
+
+public class HotSpotNativeFunctionPointer implements NativeFunctionPointer {
+
+    final long value;
+    final String name;
+
+    public HotSpotNativeFunctionPointer(long value, String name) {
+        if (value == 0) {
+            throw new UnsatisfiedLinkError(name);
+        }
+        this.value = value;
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public long getValue() {
+        return value;
+    }
+
+    @Override
+    public String toString() {
+        return name + "@0x" + Long.toHexString(value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeLibraryHandle.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, 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.nfi;
+
+import com.oracle.graal.api.code.*;
+
+public class HotSpotNativeLibraryHandle implements NativeLibraryHandle {
+
+    final long value;
+    final String name;
+
+    public HotSpotNativeLibraryHandle(String name, long handle) {
+        this.name = name;
+        this.value = handle;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof HotSpotNativeLibraryHandle) {
+            HotSpotNativeLibraryHandle that = (HotSpotNativeLibraryHandle) obj;
+            return that.value == value;
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return (int) value;
+    }
+
+    @Override
+    public String toString() {
+        return name + "@" + value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2014, 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.nfi;
+
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.word.phases.*;
+
+/**
+ * Utility creating a graph for a stub used to call a native function.
+ */
+public class NativeCallStubGraphBuilder {
+
+    /**
+     * Creates a graph for a stub used to call a native function.
+     * 
+     * @param functionPointer a native function pointer
+     * @param returnType the type of the return value
+     * @param argumentTypes the types of the arguments
+     * @return the graph that represents the call stub
+     */
+    public static StructuredGraph getGraph(HotSpotProviders providers, RawNativeCallNodeFactory factory, long functionPointer, Class returnType, Class... argumentTypes) {
+        try {
+            ResolvedJavaMethod method = providers.getMetaAccess().lookupJavaMethod(NativeCallStubGraphBuilder.class.getMethod("libCall", Object.class, Object.class, Object.class));
+            StructuredGraph g = new StructuredGraph(method);
+            ParameterNode arg0 = g.unique(new ParameterNode(0, StampFactory.forKind(Kind.Object)));
+            ParameterNode arg1 = g.unique(new ParameterNode(1, StampFactory.forKind(Kind.Object)));
+            ParameterNode arg2 = g.unique(new ParameterNode(2, StampFactory.forKind(Kind.Object)));
+            FrameState frameState = g.add(new FrameState(method, 0, Arrays.asList(new ValueNode[]{arg0, arg1, arg2}), 3, 0, false, false, new ArrayList<MonitorIdNode>(),
+                            new ArrayList<EscapeObjectState>()));
+            g.start().setStateAfter(frameState);
+            List<ValueNode> parameters = new ArrayList<>();
+            FixedWithNextNode fixedWithNext = getParameters(g, arg0, argumentTypes.length, argumentTypes, parameters, providers);
+            Constant functionPointerNode = Constant.forLong(functionPointer);
+
+            ValueNode[] arguments = new ValueNode[parameters.size()];
+
+            for (int i = 0; i < arguments.length; i++) {
+                arguments[i] = parameters.get(i);
+            }
+
+            FixedWithNextNode callNode = g.add(factory.createRawCallNode(getKind(returnType), functionPointerNode, arguments));
+
+            if (fixedWithNext == null) {
+                g.start().setNext(callNode);
+            } else {
+                fixedWithNext.setNext(callNode);
+            }
+
+            // box result
+            BoxNode boxedResult;
+            if (callNode.kind() != Kind.Void) {
+                if (callNode.kind() == Kind.Object) {
+                    throw new IllegalArgumentException("Return type not supported: " + returnType.getName());
+                }
+                ResolvedJavaType type = providers.getMetaAccess().lookupJavaType(callNode.kind().toBoxedJavaClass());
+                boxedResult = g.unique(new BoxNode(callNode, type, callNode.kind()));
+            } else {
+                boxedResult = g.unique(new BoxNode(ConstantNode.forLong(0, g), providers.getMetaAccess().lookupJavaType(Long.class), Kind.Long));
+            }
+
+            ReturnNode returnNode = g.add(new ReturnNode(boxedResult));
+            callNode.setNext(returnNode);
+            (new WordTypeRewriterPhase(providers.getMetaAccess(), Kind.Long)).apply(g);
+            return g;
+        } catch (NoSuchMethodException e) {
+            throw GraalInternalError.shouldNotReachHere("Call Stub method not found");
+        }
+    }
+
+    private static FixedWithNextNode getParameters(StructuredGraph g, ParameterNode argumentsArray, int numArgs, Class[] argumentTypes, List<ValueNode> args, HotSpotProviders providers) {
+        assert numArgs == argumentTypes.length;
+        FixedWithNextNode last = null;
+        for (int i = 0; i < numArgs; i++) {
+            // load boxed array element:
+            LoadIndexedNode boxedElement = g.add(new LoadIndexedNode(argumentsArray, ConstantNode.forInt(i, g), Kind.Object));
+            if (i == 0) {
+                g.start().setNext(boxedElement);
+                last = boxedElement;
+            } else {
+                last.setNext(boxedElement);
+                last = boxedElement;
+            }
+            Class type = argumentTypes[i];
+            Kind kind = getKind(type);
+            if (kind == Kind.Object) {
+                // array value
+                Kind arrayElementKind = getElementKind(type);
+                LocationIdentity locationIdentity = NamedLocationIdentity.getArrayLocation(arrayElementKind);
+                int displacement = getArrayBaseOffset(arrayElementKind);
+                ConstantNode index = ConstantNode.forInt(0, g);
+                int indexScaling = getArrayIndexScale(arrayElementKind);
+                IndexedLocationNode locationNode = IndexedLocationNode.create(locationIdentity, arrayElementKind, displacement, index, g, indexScaling);
+                Stamp wordStamp = StampFactory.forKind(providers.getCodeCache().getTarget().wordKind);
+                ComputeAddressNode arrayAddress = g.unique(new ComputeAddressNode(boxedElement, locationNode, wordStamp));
+                args.add(arrayAddress);
+            } else {
+                // boxed primitive value
+                try {
+                    ResolvedJavaField field = providers.getMetaAccess().lookupJavaField(kind.toBoxedJavaClass().getDeclaredField("value"));
+                    LoadFieldNode loadFieldNode = g.add(new LoadFieldNode(boxedElement, field));
+                    last.setNext(loadFieldNode);
+                    last = loadFieldNode;
+                    args.add(loadFieldNode);
+                } catch (NoSuchFieldException e) {
+                    throw new GraalInternalError(e);
+                }
+            }
+        }
+        return last;
+    }
+
+    public static Kind getElementKind(Class clazz) {
+        Class componentType = clazz.getComponentType();
+        if (componentType == null) {
+            throw new IllegalArgumentException("Parameter type not supported: " + clazz);
+        }
+        if (componentType.isPrimitive()) {
+            return Kind.fromJavaClass(componentType);
+        }
+        throw new IllegalArgumentException("Parameter type not supported: " + clazz);
+    }
+
+    private static Kind getKind(Class clazz) {
+        if (clazz == int.class || clazz == Integer.class) {
+            return Kind.Int;
+        } else if (clazz == long.class || clazz == Long.class) {
+            return Kind.Long;
+        } else if (clazz == char.class || clazz == Character.class) {
+            return Kind.Char;
+        } else if (clazz == byte.class || clazz == Byte.class) {
+            return Kind.Byte;
+        } else if (clazz == float.class || clazz == Float.class) {
+            return Kind.Float;
+        } else if (clazz == double.class || clazz == Double.class) {
+            return Kind.Double;
+        } else if (clazz == int[].class || clazz == long[].class || clazz == char[].class || clazz == byte[].class || clazz == float[].class || clazz == double[].class) {
+            return Kind.Object;
+        } else if (clazz == void.class) {
+            return Kind.Void;
+        } else {
+            throw new IllegalArgumentException("Type not supported: " + clazz);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static Object libCall(Object argLoc, Object unused1, Object unused2) {
+        throw GraalInternalError.shouldNotReachHere("GNFI libCall method must not be called");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/RawNativeCallNodeFactory.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 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.nfi;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Factory for creating a node that makes a direct call to a native function pointer.
+ */
+public interface RawNativeCallNodeFactory {
+    FixedWithNextNode createRawCallNode(Kind returnType, Constant functionPointer, ValueNode... args);
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Mon Feb 17 13:48:41 2014 +0100
@@ -63,7 +63,7 @@
             ConstantNode klassNode = ConstantNode.forConstant(klass, metaAccess, graph);
 
             Stamp stamp = StampFactory.exactNonNull(metaAccess.lookupJavaType(Class.class));
-            LocationNode location = graph.unique(ConstantLocationNode.create(FINAL_LOCATION, stamp.kind(), classMirrorOffset, graph));
+            LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, stamp.kind(), classMirrorOffset, graph);
             FloatingReadNode freadNode = graph.unique(new FloatingReadNode(klassNode, location, null, stamp));
             return freadNode;
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.replacements;
 
 import static com.oracle.graal.compiler.GraalCompiler.*;
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
@@ -63,6 +64,10 @@
         return arguments.get(4);
     }
 
+    private static boolean isHeapWordAligned(Constant value, Kind kind) {
+        return (arrayBaseOffset(kind) + value.asInt() * arrayIndexScale(kind)) % heapWordSize() == 0;
+    }
+
     private StructuredGraph selectSnippet(LoweringTool tool, final Replacements replacements) {
         ResolvedJavaType srcType = ObjectStamp.typeOrNull(getSource().stamp());
         ResolvedJavaType destType = ObjectStamp.typeOrNull(getDestination().stamp());
@@ -74,7 +79,23 @@
             return null;
         }
         Kind componentKind = srcType.getComponentType().getKind();
-        final ResolvedJavaMethod snippetMethod = tool.getMetaAccess().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(componentKind));
+        boolean disjoint = false;
+        boolean aligned = false;
+        if (getSourcePosition() == getDestinationPosition()) {
+            // Can treat as disjoint
+            disjoint = true;
+        }
+        Constant constantSrc = getSourcePosition().stamp().asConstant();
+        Constant constantDst = getDestinationPosition().stamp().asConstant();
+        if (constantSrc != null && constantDst != null) {
+            aligned = isHeapWordAligned(constantSrc, componentKind) && isHeapWordAligned(constantDst, componentKind);
+            if (constantSrc.asInt() >= constantDst.asInt()) {
+                // low to high copy so treat as disjoint
+                disjoint = true;
+            }
+        }
+
+        final ResolvedJavaMethod snippetMethod = tool.getMetaAccess().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(componentKind, aligned, disjoint));
         try (Scope s = Debug.scope("ArrayCopySnippet", snippetMethod)) {
             return replacements.getSnippet(snippetMethod);
         } catch (Throwable e) {
@@ -188,4 +209,5 @@
             }
         }
     }
+
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Mon Feb 17 13:48:41 2014 +0100
@@ -35,6 +35,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -51,13 +52,47 @@
 public class ArrayCopySnippets implements Snippets {
 
     private static final EnumMap<Kind, Method> arraycopyMethods = new EnumMap<>(Kind.class);
+    private static final EnumMap[][] arraycopyCalls = new EnumMap[2][2];
+    private static final EnumMap[][] arraycopyDescriptors = new EnumMap[2][2];
+
     public static final Method genericArraycopySnippet;
 
+    @SuppressWarnings("unchecked")
+    private static void findArraycopyCall(Kind kind, Class<?> arrayClass, boolean aligned, boolean disjoint) throws NoSuchMethodException {
+        String name = kind + (aligned ? "Aligned" : "") + (disjoint ? "Disjoint" : "") + "Arraycopy";
+        arraycopyCalls[aligned ? 1 : 0][disjoint ? 1 : 0].put(kind, ArrayCopySnippets.class.getDeclaredMethod(name, arrayClass, int.class, arrayClass, int.class, int.class));
+        arraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0].put(kind, new ForeignCallDescriptor(name, void.class, Word.class, Word.class, Word.class));
+    }
+
+    private static Method lookupArraycopyCall(Kind kind, boolean aligned, boolean disjoint) {
+        return (Method) arraycopyCalls[aligned ? 1 : 0][disjoint ? 1 : 0].get(kind);
+    }
+
+    @Fold
+    public static ForeignCallDescriptor lookupArraycopyDescriptor(Kind kind, boolean aligned, boolean disjoint) {
+        return (ForeignCallDescriptor) arraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0].get(kind);
+    }
+
     private static void addArraycopySnippetMethod(Kind kind, Class<?> arrayClass) throws NoSuchMethodException {
         arraycopyMethods.put(kind, ArrayCopySnippets.class.getDeclaredMethod("arraycopy", arrayClass, int.class, arrayClass, int.class, int.class));
+        if (CallArrayCopy.getValue()) {
+            if (kind != Kind.Object) {
+                // Only primitive types are currently supported
+                findArraycopyCall(kind, arrayClass, false, false);
+                findArraycopyCall(kind, arrayClass, false, true);
+                findArraycopyCall(kind, arrayClass, true, false);
+                findArraycopyCall(kind, arrayClass, true, true);
+            }
+        }
     }
 
     static {
+        for (int i = 0; i < arraycopyCalls.length; i++) {
+            for (int j = 0; j < arraycopyCalls[i].length; j++) {
+                arraycopyCalls[i][j] = new EnumMap<Kind, Method>(Kind.class);
+                arraycopyDescriptors[i][j] = new EnumMap<Kind, ForeignCallDescriptor>(Kind.class);
+            }
+        }
         try {
             addArraycopySnippetMethod(Kind.Byte, byte[].class);
             addArraycopySnippetMethod(Kind.Boolean, boolean[].class);
@@ -74,7 +109,11 @@
         }
     }
 
-    public static Method getSnippetForKind(Kind kind) {
+    public static Method getSnippetForKind(Kind kind, boolean aligned, boolean disjoint) {
+        Method m = lookupArraycopyCall(kind, aligned, disjoint);
+        if (m != null) {
+            return m;
+        }
         return arraycopyMethods.get(kind);
     }
 
@@ -195,6 +234,186 @@
         }
     }
 
+    @NodeIntrinsic(ForeignCallNode.class)
+    public static native void callArraycopy(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word src, Word dst, Word len);
+
+    private static Word computeBase(Object object, Kind kind, int pos) {
+        // In this code pos must be cast to long before being multiplied since shifting the value
+        // could be outside the range of int. arrayIndexScale should probably either return long or
+        // Word to force the right thing to happen.
+        return Word.unsigned(GetObjectAddressNode.get(object) + arrayBaseOffset(kind) + (long) pos * arrayIndexScale(kind));
+    }
+
+    private static void callArraycopyTemplate(SnippetCounter counter, Kind kind, boolean aligned, boolean disjoint, Object src, int srcPos, Object dest, int destPos, int length) {
+        counter.inc();
+        Object nonNullSrc = guardingNonNull(src);
+        Object nonNullDest = guardingNonNull(dest);
+        checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length);
+        Word srcAddr = computeBase(src, kind, srcPos);
+        Word destAddr = computeBase(dest, kind, destPos);
+        callArraycopy(lookupArraycopyDescriptor(kind, aligned, disjoint), srcAddr, destAddr, Word.signed(length));
+    }
+
+    @Snippet
+    public static void byteArraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
+        callArraycopyTemplate(byteCallCounter, Kind.Byte, false, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void byteDisjointArraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
+        callArraycopyTemplate(byteDisjointCallCounter, Kind.Byte, false, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void byteAlignedArraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
+        callArraycopyTemplate(byteAlignedCallCounter, Kind.Byte, true, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void byteAlignedDisjointArraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
+        callArraycopyTemplate(byteAlignedDisjointCallCounter, Kind.Byte, true, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void booleanArraycopy(boolean[] src, int srcPos, boolean[] dest, int destPos, int length) {
+        callArraycopyTemplate(booleanCallCounter, Kind.Boolean, false, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void booleanDisjointArraycopy(boolean[] src, int srcPos, boolean[] dest, int destPos, int length) {
+        callArraycopyTemplate(booleanDisjointCallCounter, Kind.Boolean, false, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void booleanAlignedArraycopy(boolean[] src, int srcPos, boolean[] dest, int destPos, int length) {
+        callArraycopyTemplate(booleanAlignedCallCounter, Kind.Boolean, true, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void booleanAlignedDisjointArraycopy(boolean[] src, int srcPos, boolean[] dest, int destPos, int length) {
+        callArraycopyTemplate(booleanAlignedDisjointCallCounter, Kind.Boolean, true, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void charArraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) {
+        callArraycopyTemplate(charCallCounter, Kind.Char, false, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void charDisjointArraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) {
+        callArraycopyTemplate(charDisjointCallCounter, Kind.Char, false, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void charAlignedArraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) {
+        callArraycopyTemplate(charAlignedCallCounter, Kind.Char, true, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void charAlignedDisjointArraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) {
+        callArraycopyTemplate(charAlignedDisjointCallCounter, Kind.Char, true, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void shortArraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) {
+        callArraycopyTemplate(shortCallCounter, Kind.Short, false, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void shortDisjointArraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) {
+        callArraycopyTemplate(shortDisjointCallCounter, Kind.Short, false, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void shortAlignedArraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) {
+        callArraycopyTemplate(shortAlignedCallCounter, Kind.Short, true, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void shortAlignedDisjointArraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) {
+        callArraycopyTemplate(shortAlignedDisjointCallCounter, Kind.Short, true, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void intArraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) {
+        callArraycopyTemplate(intCallCounter, Kind.Int, false, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void intDisjointArraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) {
+        callArraycopyTemplate(intDisjointCallCounter, Kind.Int, false, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void intAlignedArraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) {
+        callArraycopyTemplate(intAlignedCallCounter, Kind.Int, true, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void intAlignedDisjointArraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) {
+        callArraycopyTemplate(intAlignedDisjointCallCounter, Kind.Int, true, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void floatArraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) {
+        callArraycopyTemplate(floatCallCounter, Kind.Float, false, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void floatDisjointArraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) {
+        callArraycopyTemplate(floatDisjointCallCounter, Kind.Float, false, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void floatAlignedArraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) {
+        callArraycopyTemplate(floatAlignedCallCounter, Kind.Float, true, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void floatAlignedDisjointArraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) {
+        callArraycopyTemplate(floatAlignedDisjointCallCounter, Kind.Float, true, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void longArraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) {
+        callArraycopyTemplate(longCallCounter, Kind.Long, false, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void longDisjointArraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) {
+        callArraycopyTemplate(longDisjointCallCounter, Kind.Long, false, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void longAlignedArraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) {
+        callArraycopyTemplate(longAlignedCallCounter, Kind.Long, true, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void longAlignedDisjointArraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) {
+        callArraycopyTemplate(longAlignedDisjointCallCounter, Kind.Long, true, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void doubleArraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) {
+        callArraycopyTemplate(doubleCallCounter, Kind.Double, false, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void doubleDisjointArraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) {
+        callArraycopyTemplate(doubleDisjointCallCounter, Kind.Double, false, true, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void doubleAlignedArraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) {
+        callArraycopyTemplate(doubleAlignedCallCounter, Kind.Double, true, false, src, srcPos, dest, destPos, length);
+    }
+
+    @Snippet
+    public static void doubleAlignedDisjointArraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) {
+        callArraycopyTemplate(doubleAlignedDisjointCallCounter, Kind.Double, true, true, src, srcPos, dest, destPos, length);
+    }
+
     private static final SnippetCounter.Group checkCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy checkInputs") : null;
     private static final SnippetCounter checkSuccessCounter = new SnippetCounter(checkCounters, "checkSuccess", "checkSuccess");
     private static final SnippetCounter checkNPECounter = new SnippetCounter(checkCounters, "checkNPE", "checkNPE");
@@ -210,6 +429,40 @@
     private static final SnippetCounter objectCounter = new SnippetCounter(counters, "Object[]", "arraycopy for Object[] arrays");
     private static final SnippetCounter floatCounter = new SnippetCounter(counters, "float[]", "arraycopy for float[] arrays");
     private static final SnippetCounter doubleCounter = new SnippetCounter(counters, "double[]", "arraycopy for double[] arrays");
+
+    private static final SnippetCounter booleanAlignedCallCounter = new SnippetCounter(counters, "boolean[]", "aligned arraycopy call for boolean[] arrays");
+    private static final SnippetCounter booleanAlignedDisjointCallCounter = new SnippetCounter(counters, "boolean[]", "aligned disjoint arraycopy call for boolean[] arrays");
+    private static final SnippetCounter booleanCallCounter = new SnippetCounter(counters, "boolean[]", "arraycopy call for boolean[] arrays");
+    private static final SnippetCounter booleanDisjointCallCounter = new SnippetCounter(counters, "boolean[]", "disjoint arraycopy call for boolean[] arrays");
+    private static final SnippetCounter byteAlignedCallCounter = new SnippetCounter(counters, "byte[]", "aligned arraycopy call for byte[] arrays");
+    private static final SnippetCounter byteAlignedDisjointCallCounter = new SnippetCounter(counters, "byte[]", "aligned disjoint arraycopy call for byte[] arrays");
+    private static final SnippetCounter byteCallCounter = new SnippetCounter(counters, "byte[]", "arraycopy call for byte[] arrays");
+    private static final SnippetCounter byteDisjointCallCounter = new SnippetCounter(counters, "byte[]", "disjoint arraycopy call for byte[] arrays");
+    private static final SnippetCounter charAlignedCallCounter = new SnippetCounter(counters, "char[]", "aligned arraycopy call for char[] arrays");
+    private static final SnippetCounter charAlignedDisjointCallCounter = new SnippetCounter(counters, "char[]", "aligned disjoint arraycopy call for char[] arrays");
+    private static final SnippetCounter charCallCounter = new SnippetCounter(counters, "char[]", "arraycopy call for char[] arrays");
+    private static final SnippetCounter charDisjointCallCounter = new SnippetCounter(counters, "char[]", "disjoint arraycopy call for char[] arrays");
+    private static final SnippetCounter doubleAlignedCallCounter = new SnippetCounter(counters, "double[]", "aligned arraycopy call for double[] arrays");
+    private static final SnippetCounter doubleAlignedDisjointCallCounter = new SnippetCounter(counters, "double[]", "aligned disjoint arraycopy call for double[] arrays");
+    private static final SnippetCounter doubleCallCounter = new SnippetCounter(counters, "double[]", "arraycopy call for double[] arrays");
+    private static final SnippetCounter doubleDisjointCallCounter = new SnippetCounter(counters, "double[]", "disjoint arraycopy call for double[] arrays");
+    private static final SnippetCounter floatAlignedCallCounter = new SnippetCounter(counters, "float[]", "aligned arraycopy call for float[] arrays");
+    private static final SnippetCounter floatAlignedDisjointCallCounter = new SnippetCounter(counters, "float[]", "aligned disjoint arraycopy call for float[] arrays");
+    private static final SnippetCounter floatCallCounter = new SnippetCounter(counters, "float[]", "arraycopy call for float[] arrays");
+    private static final SnippetCounter floatDisjointCallCounter = new SnippetCounter(counters, "float[]", "disjoint arraycopy call for float[] arrays");
+    private static final SnippetCounter intAlignedCallCounter = new SnippetCounter(counters, "int[]", "aligned arraycopy call for int[] arrays");
+    private static final SnippetCounter intAlignedDisjointCallCounter = new SnippetCounter(counters, "int[]", "aligned disjoint arraycopy call for int[] arrays");
+    private static final SnippetCounter intCallCounter = new SnippetCounter(counters, "int[]", "arraycopy call for int[] arrays");
+    private static final SnippetCounter intDisjointCallCounter = new SnippetCounter(counters, "int[]", "disjoint arraycopy call for int[] arrays");
+    private static final SnippetCounter longAlignedCallCounter = new SnippetCounter(counters, "long[]", "aligned arraycopy call for long[] arrays");
+    private static final SnippetCounter longAlignedDisjointCallCounter = new SnippetCounter(counters, "long[]", "aligned disjoint arraycopy call for long[] arrays");
+    private static final SnippetCounter longCallCounter = new SnippetCounter(counters, "long[]", "arraycopy call for long[] arrays");
+    private static final SnippetCounter longDisjointCallCounter = new SnippetCounter(counters, "long[]", "disjoint arraycopy call for long[] arrays");
+    private static final SnippetCounter shortAlignedCallCounter = new SnippetCounter(counters, "short[]", "aligned arraycopy call for short[] arrays");
+    private static final SnippetCounter shortAlignedDisjointCallCounter = new SnippetCounter(counters, "short[]", "aligned disjoint arraycopy call for short[] arrays");
+    private static final SnippetCounter shortCallCounter = new SnippetCounter(counters, "short[]", "arraycopy call for short[] arrays");
+    private static final SnippetCounter shortDisjointCallCounter = new SnippetCounter(counters, "short[]", "disjoint arraycopy call for short[] arrays");
+
     private static final SnippetCounter genericPrimitiveCallCounter = new SnippetCounter(counters, "genericPrimitive", "generic arraycopy snippet for primitive arrays");
     private static final SnippetCounter genericObjectExactCallCounter = new SnippetCounter(counters, "genericObjectExact", "generic arraycopy snippet for special object arrays");
     private static final SnippetCounter genericObjectCallCounter = new SnippetCounter(counters, "genericObject", "call to the generic, native arraycopy method");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Feb 17 13:48:41 2014 +0100
@@ -211,6 +211,11 @@
         return Unsafe.getUnsafe().pageSize();
     }
 
+    @Fold
+    public static int heapWordSize() {
+        return config().heapWordSize;
+    }
+
     public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = new NamedLocationIdentity("PrototypeMarkWord");
 
     @Fold
@@ -718,14 +723,4 @@
             throw new GraalInternalError(e);
         }
     }
-
-    @Fold
-    public static long dllLoad() {
-        return config().libraryLoadAddress;
-    }
-
-    @Fold
-    public static long dllLookup() {
-        return config().functionLookupAddress;
-    }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Feb 17 13:48:41 2014 +0100
@@ -950,12 +950,16 @@
                 dims[i] = frameState.ipop();
             }
             if (type instanceof ResolvedJavaType) {
-                frameState.apush(append(new NewMultiArrayNode((ResolvedJavaType) type, dims)));
+                frameState.apush(append(createNewMultiArray((ResolvedJavaType) type, dims)));
             } else {
                 handleUnresolvedNewMultiArray(type, dims);
             }
         }
 
+        protected NewMultiArrayNode createNewMultiArray(ResolvedJavaType type, ValueNode[] dimensions) {
+            return new NewMultiArrayNode(type, dimensions);
+        }
+
         private void genGetField(JavaField field) {
             emitExplicitExceptions(frameState.peek(0), null);
 
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_i2b.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_i2b.java	Mon Feb 17 13:48:41 2014 +0100
@@ -53,4 +53,27 @@
         runTest("test", 128);
     }
 
+    public static int testInt(int a) {
+        return (byte) a;
+    }
+
+    @Test
+    public void runI0() throws Throwable {
+        runTest("testInt", -1);
+    }
+
+    @Test
+    public void runI1() throws Throwable {
+        runTest("testInt", 2);
+    }
+
+    @Test
+    public void runI2() throws Throwable {
+        runTest("testInt", 255);
+    }
+
+    @Test
+    public void runI3() throws Throwable {
+        runTest("testInt", 128);
+    }
 }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_i2c.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_i2c.java	Mon Feb 17 13:48:41 2014 +0100
@@ -48,4 +48,22 @@
         runTest("test", 65535);
     }
 
+    public static int testInt(int a) {
+        return (char) a;
+    }
+
+    @Test
+    public void runI0() throws Throwable {
+        runTest("testInt", -1);
+    }
+
+    @Test
+    public void runI1() throws Throwable {
+        runTest("testInt", 645);
+    }
+
+    @Test
+    public void runI2() throws Throwable {
+        runTest("testInt", 65535);
+    }
 }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_i2s.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_i2s.java	Mon Feb 17 13:48:41 2014 +0100
@@ -53,4 +53,27 @@
         runTest("test", 32768);
     }
 
+    public static int testInt(int a) {
+        return (short) a;
+    }
+
+    @Test
+    public void runI0() throws Throwable {
+        runTest("testInt", -1);
+    }
+
+    @Test
+    public void runI1() throws Throwable {
+        runTest("testInt", 34);
+    }
+
+    @Test
+    public void runI2() throws Throwable {
+        runTest("testInt", 65535);
+    }
+
+    @Test
+    public void runI3() throws Throwable {
+        runTest("testInt", 32768);
+    }
 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Mon Feb 17 13:48:41 2014 +0100
@@ -73,12 +73,23 @@
                 default:   throw GraalInternalError.shouldNotReachHere();
             }
         } else if (isConstant(y)) {
+            boolean isZero = ((Constant) y).isDefaultForKind();
             switch (opcode) {
-                case ICMP: masm.cmpl(asIntReg(x), crb.asIntConst(y)); break;
-                case LCMP: masm.cmpq(asLongReg(x), crb.asIntConst(y)); break;
+                case ICMP: if (isZero) {
+                    masm.testl(asIntReg(x), asIntReg(x));
+                } else {
+                    masm.cmpl(asIntReg(x), crb.asIntConst(y));
+                }
+                break;
+                case LCMP: if (isZero) {
+                    masm.testq(asLongReg(x), asLongReg(x));
+                } else {
+                    masm.cmpq(asLongReg(x), crb.asIntConst(y));
+                }
+                break;
                 case ACMP:
-                    if (((Constant) y).isNull()) {
-                        masm.cmpq(asObjectReg(x), 0); break;
+                    if (isZero) {
+                        masm.testq(asObjectReg(x), asObjectReg(x)); break;
                     } else {
                         throw GraalInternalError.shouldNotReachHere("Only null object constants are allowed in comparisons");
                     }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Mon Feb 17 13:48:41 2014 +0100
@@ -61,28 +61,39 @@
         protected final LabelRef trueDestination;
         protected final LabelRef falseDestination;
 
-        public BranchOp(Condition condition, LabelRef trueDestination, LabelRef falseDestination) {
-            this(intCond(condition), trueDestination, falseDestination);
+        private final double trueDestinationProbability;
+
+        public BranchOp(Condition condition, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
+            this(intCond(condition), trueDestination, falseDestination, trueDestinationProbability);
         }
 
-        public BranchOp(ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination) {
+        public BranchOp(ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
             this.condition = condition;
             this.trueDestination = trueDestination;
             this.falseDestination = falseDestination;
+            this.trueDestinationProbability = trueDestinationProbability;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            /*
+             * The strategy for emitting jumps is: If either trueDestination or falseDestination is
+             * the successor block, assume the block scheduler did the correct thing and jcc to the
+             * other. Otherwise, we need a jcc followed by a jmp. Use the branch probability to make
+             * sure it is more likely to branch on the jcc (= less likely to execute both the jcc
+             * and the jmp instead of just the jcc). In the case of loops, that means the jcc is the
+             * back-edge.
+             */
             if (crb.isSuccessorEdge(trueDestination)) {
                 jcc(masm, true, falseDestination);
-            } else if (falseDestination.getSourceBlock() == falseDestination.getTargetBlock()) {
+            } else if (crb.isSuccessorEdge(falseDestination)) {
+                jcc(masm, false, trueDestination);
+            } else if (trueDestinationProbability < 0.5) {
                 jcc(masm, true, falseDestination);
                 masm.jmp(trueDestination.label());
             } else {
                 jcc(masm, false, trueDestination);
-                if (!crb.isSuccessorEdge(falseDestination)) {
-                    masm.jmp(falseDestination.label());
-                }
+                masm.jmp(falseDestination.label());
             }
         }
 
@@ -94,8 +105,8 @@
     public static class FloatBranchOp extends BranchOp {
         protected boolean unorderedIsTrue;
 
-        public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination) {
-            super(floatCond(condition), trueDestination, falseDestination);
+        public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
+            super(floatCond(condition), trueDestination, falseDestination, trueDestinationProbability);
             this.unorderedIsTrue = unorderedIsTrue;
         }
 
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Mon Feb 17 13:48:41 2014 +0100
@@ -139,6 +139,8 @@
         public void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
             switch (kind) {
                 case Boolean:
+                    masm.movzbl(asRegister(result), address.toAddress());
+                    break;
                 case Byte:
                     masm.movsbl(asRegister(result), address.toAddress());
                     break;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Mon Feb 17 13:48:41 2014 +0100
@@ -122,6 +122,10 @@
         return frameSize;
     }
 
+    public int outgoingSize() {
+        return outgoingSize;
+    }
+
     /**
      * Determines if any space is used in the frame apart from the
      * {@link Architecture#getReturnAddressSize() return address slot}.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Mon Feb 17 13:48:41 2014 +0100
@@ -160,7 +160,7 @@
     public void recordInlineDataInCode(Constant data) {
         assert data != null;
         int pos = asm.codeBuffer.position();
-        Debug.log("Inline data in code: pos = %d, data = %s", pos, data.toString());
+        Debug.log("Inline data in code: pos = %d, data = %s", pos, data);
         compilationResult.recordInlineData(pos, data);
     }
 
@@ -172,7 +172,7 @@
     public AbstractAddress recordDataReferenceInCode(Data data) {
         assert data != null;
         int pos = asm.codeBuffer.position();
-        Debug.log("Data reference in code: pos = %d, data = %s", pos, data.toString());
+        Debug.log("Data reference in code: pos = %d, data = %s", pos, data);
         compilationResult.recordDataReference(pos, data);
         return asm.getPlaceholder();
     }
--- a/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionHandle.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2014, 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.nfi.hotspot.amd64;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.nfi.hotspot.amd64.util.*;
-import com.oracle.graal.nodes.*;
-
-public class AMD64HotSpotNativeFunctionHandle implements NativeFunctionHandle {
-
-    private final InstalledCode code;
-    private final String functionName;
-
-    protected final HotSpotProviders providers;
-    protected final Backend backend;
-
-    public AMD64HotSpotNativeFunctionHandle(HotSpotProviders providers, Backend backend, AMD64HotSpotNativeFunctionPointer functionPointer, Class returnType, Class[] argumentTypes) {
-        this.providers = providers;
-        this.backend = backend;
-        this.functionName = functionPointer.getFunctionName();
-        StructuredGraph graph = NativeCallStubGraphBuilder.getGraph(providers, functionPointer, returnType, argumentTypes);
-        InstallUtil installer = new InstallUtil(providers, backend);
-        this.code = installer.install(graph);
-    }
-
-    @Override
-    public Object call(Object[] args) {
-        try {
-            return code.execute(args, null, null);
-        } catch (InvalidInstalledCodeException e) {
-            throw GraalInternalError.shouldNotReachHere("Execution of GNFI Callstub failed: " + functionName);
-        }
-    }
-
-    public InstalledCode getCallStub() {
-        return code;
-    }
-}
--- a/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionInterface.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2014, 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.nfi.hotspot.amd64;
-
-import java.lang.reflect.*;
-
-import sun.misc.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.meta.*;
-
-public class AMD64HotSpotNativeFunctionInterface implements NativeFunctionInterface {
-
-    private static final Class LOOKUP_FUNCTION_RETURNTYPE = long.class;
-    private static final Class[] LOOKUP_FUNCTION_SIGNATURE = new Class[]{long.class, long.class};
-
-    private static final Unsafe unsafe = getUnsafe();
-
-    private static final int STD_BUFFER_SIZE = 1024;
-
-    protected final HotSpotProviders providers;
-    protected final Backend backend;
-    protected final AMD64HotSpotNativeLibraryHandle rtldDefault;
-    protected final AMD64HotSpotNativeFunctionPointer libraryLoadFunctionPointer;
-    protected final AMD64HotSpotNativeFunctionPointer functionLookupFunctionPointer;
-
-    private AMD64HotSpotNativeFunctionHandle libraryLookupFunctionHandle;
-    private AMD64HotSpotNativeFunctionHandle dllLookupFunctionHandle;
-
-    public AMD64HotSpotNativeFunctionInterface(HotSpotProviders providers, Backend backend, AMD64HotSpotNativeFunctionPointer libraryLoadFunctionPointer,
-                    AMD64HotSpotNativeFunctionPointer functionLookUpFunctionPointer, AMD64HotSpotNativeLibraryHandle rtldDefault) {
-        this.rtldDefault = rtldDefault;
-        this.providers = providers;
-        this.backend = backend;
-        this.libraryLoadFunctionPointer = libraryLoadFunctionPointer;
-        this.functionLookupFunctionPointer = functionLookUpFunctionPointer;
-    }
-
-    @Override
-    public AMD64HotSpotNativeLibraryHandle getLibraryHandle(String libPath) {
-        if (libraryLookupFunctionHandle == null) {
-            libraryLookupFunctionHandle = new AMD64HotSpotNativeFunctionHandle(providers, backend, libraryLoadFunctionPointer, long.class, new Class[]{long.class, long.class, int.class});
-        }
-
-        long allocatedMemory = -1;
-        try {
-            allocatedMemory = unsafe.allocateMemory(STD_BUFFER_SIZE);
-        } catch (OutOfMemoryError e) {
-            throw new AssertionError();
-        }
-
-        Object[] args = new Object[]{copyStringToMemory(libPath), allocatedMemory, STD_BUFFER_SIZE};
-        long libraryHandle = (long) libraryLookupFunctionHandle.call(args);
-        unsafe.freeMemory(allocatedMemory);
-        return new AMD64HotSpotNativeLibraryHandle(libraryHandle);
-    }
-
-    @Override
-    public AMD64HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle libraryHandle, String functionName, Class returnType, Class[] argumentTypes) {
-        AMD64HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(functionName, libraryHandle);
-        if (!functionPointer.isValid()) {
-            throw new IllegalStateException(functionName + " not found!");
-        }
-        return getFunctionHandle(functionPointer, returnType, argumentTypes);
-    }
-
-    @Override
-    public AMD64HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraryHandles, String functionName, Class returnType, Class[] argumentTypes) {
-        AMD64HotSpotNativeFunctionPointer functionPointer = null;
-        for (NativeLibraryHandle libraryHandle : libraryHandles) {
-            functionPointer = lookupFunctionPointer(functionName, libraryHandle);
-            if (functionPointer.isValid()) {
-                return new AMD64HotSpotNativeFunctionHandle(providers, backend, functionPointer, returnType, argumentTypes);
-            }
-        }
-        return getFunctionHandle(functionName, returnType, argumentTypes);
-    }
-
-    @Override
-    public AMD64HotSpotNativeFunctionHandle getFunctionHandle(String functionName, Class returnType, Class[] argumentTypes) {
-        if (rtldDefault.asRawValue() == HotSpotVMConfig.INVALID_RTLD_DEFAULT_HANDLE) {
-            throw new AssertionError("No library provided or RTLD_DEFAULT not supported!");
-        }
-        return getFunctionHandle(rtldDefault, functionName, returnType, argumentTypes);
-    }
-
-    private AMD64HotSpotNativeFunctionPointer lookupFunctionPointer(String functionName, NativeLibraryHandle handle) {
-
-        if (!functionLookupFunctionPointer.isValid()) {
-            throw new IllegalStateException("no dlsym function pointer");
-        }
-        if (dllLookupFunctionHandle == null) {
-            dllLookupFunctionHandle = new AMD64HotSpotNativeFunctionHandle(providers, backend, functionLookupFunctionPointer, LOOKUP_FUNCTION_RETURNTYPE, LOOKUP_FUNCTION_SIGNATURE);
-        }
-        long allocatedMemory = copyStringToMemory(functionName);
-        Object[] args = new Object[]{handle, allocatedMemory};
-        long functionPointer = (long) dllLookupFunctionHandle.call(args);
-        unsafe.freeMemory(allocatedMemory);
-        return new AMD64HotSpotNativeFunctionPointer(functionPointer, functionName);
-    }
-
-    private static long copyStringToMemory(String str) {
-        int size = str.length();
-        long ptr = unsafe.allocateMemory(size + 1);
-        for (int i = 0; i < size; i++) {
-            unsafe.putByte(ptr + i, (byte) str.charAt(i));
-        }
-        unsafe.putByte(ptr + size, (byte) '\0');
-        return ptr;
-    }
-
-    private static Unsafe getUnsafe() {
-        try {
-            return Unsafe.getUnsafe();
-        } catch (SecurityException e) {
-        }
-        try {
-            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
-            theUnsafeInstance.setAccessible(true);
-            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
-        } catch (IllegalArgumentException | SecurityException | NoSuchFieldException | IllegalAccessException e) {
-            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
-        }
-    }
-
-    @Override
-    public AMD64HotSpotNativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class[] argumentTypes) {
-        if (functionPointer instanceof AMD64HotSpotNativeFunctionPointer) {
-            if (!((AMD64HotSpotNativeFunctionPointer) functionPointer).isValid()) {
-                throw new IllegalStateException("Function Symbol not found");
-            }
-        } else {
-            throw new IllegalStateException("AMD64 function pointer required!");
-        }
-        return new AMD64HotSpotNativeFunctionHandle(providers, backend, (AMD64HotSpotNativeFunctionPointer) functionPointer, returnType, argumentTypes);
-    }
-
-    @Override
-    public AMD64HotSpotNativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraryHandles, String functionName) {
-        for (NativeLibraryHandle libraryHandle : libraryHandles) {
-            AMD64HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(functionName, libraryHandle);
-            if (functionPointer.isValid()) {
-                return functionPointer;
-            }
-        }
-        throw new LinkageError("Function not found: " + functionName);
-    }
-
-    @Override
-    public NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue) {
-        return new AMD64HotSpotNativeFunctionPointer(rawValue, null);
-    }
-
-}
--- a/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionPointer.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2014, 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.nfi.hotspot.amd64;
-
-import com.oracle.graal.api.code.*;
-
-public class AMD64HotSpotNativeFunctionPointer implements NativeFunctionPointer {
-
-    private final long functionPointer;
-    private final String functionName;
-
-    public AMD64HotSpotNativeFunctionPointer(long functionPointer, String functionName) {
-        this.functionPointer = functionPointer;
-        this.functionName = functionName;
-    }
-
-    public boolean isValid() {
-        return functionPointer != 0;
-    }
-
-    @Override
-    public long asRawValue() {
-        return functionPointer;
-    }
-
-    public String getFunctionName() {
-        return functionName;
-    }
-
-}
--- a/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeLibraryHandle.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2014, 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.nfi.hotspot.amd64;
-
-import com.oracle.graal.api.code.*;
-
-public class AMD64HotSpotNativeLibraryHandle implements NativeLibraryHandle {
-
-    private final long handle;
-
-    public AMD64HotSpotNativeLibraryHandle(long handle) {
-        this.handle = handle;
-    }
-
-    public long asRawValue() {
-        return handle;
-    }
-
-    public boolean isValid() {
-        return handle != 0;
-    }
-}
--- a/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/node/AMD64RawNativeCallNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2014, 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.nfi.hotspot.amd64.node;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CallingConvention.Type;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.amd64.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
-
-public class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRGenLowerable {
-
-    private final Constant functionPointer;
-    @Input private final NodeInputList<ValueNode> args;
-
-    public AMD64RawNativeCallNode(Kind returnType, Constant functionPointer, ValueNode[] args) {
-        super(StampFactory.forKind(returnType));
-        this.functionPointer = functionPointer;
-        this.args = new NodeInputList<>(this, args);
-    }
-
-    @Override
-    public void generate(LIRGenerator generator) {
-        if (generator instanceof AMD64LIRGenerator) {
-            AMD64LIRGenerator amd64gen = (AMD64LIRGenerator) generator;
-            Value[] parameter = new Value[args.count()];
-            JavaType[] parameterTypes = new JavaType[args.count()];
-            for (int i = 0; i < args.count(); i++) {
-                parameter[i] = generator.operand(args.get(i));
-                parameterTypes[i] = args.get(i).stamp().javaType(amd64gen.getMetaAccess());
-            }
-            ResolvedJavaType returnType = stamp().javaType(amd64gen.getMetaAccess());
-            CallingConvention cc = generator.getCodeCache().getRegisterConfig().getCallingConvention(Type.NativeCall, returnType, parameterTypes, generator.target(), false);
-            amd64gen.emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args));
-            if (this.kind() != Kind.Void) {
-                generator.setResult(this, amd64gen.emitMove(cc.getReturn()));
-            }
-        } else {
-            throw GraalInternalError.shouldNotReachHere("GNFI Native call only supported with AMD64LIR Generator");
-        }
-    }
-
-    private static int countFloatingTypeArguments(NodeInputList<ValueNode> args) {
-        int count = 0;
-        for (ValueNode n : args) {
-            if (n.kind() == Kind.Double || n.kind() == Kind.Float) {
-                count++;
-            }
-        }
-        if (count > 8) {
-            return 8;
-        }
-        return count;
-    }
-
-}
--- a/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/util/InstallUtil.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2014, 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.nfi.hotspot.amd64.util;
-
-import static com.oracle.graal.api.code.CodeUtil.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CallingConvention.Type;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.tiers.*;
-import com.oracle.graal.printer.*;
-
-/**
- * Utility to install the code of the native call stub.
- * 
- */
-public class InstallUtil {
-
-    protected final HotSpotProviders providers;
-    protected final Backend backend;
-
-    public InstallUtil(HotSpotProviders providers, Backend backend) {
-        DebugEnvironment.initialize(System.out);
-        this.providers = providers;
-        this.backend = backend;
-    }
-
-    /**
-     * Attaches a graph to a method libCall. Compiles the graph and installs it.
-     * 
-     * @param g the graph to be attached to a method and compiled
-     * @return returns the installed code that also holds a copy of graph g
-     */
-    public InstalledCode install(final StructuredGraph g) {
-        try {
-            Suites suites = providers.getSuites().createSuites();
-            PhaseSuite<HighTierContext> phaseSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy();
-            CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, g.method(), false);
-            CompilationResult compResult = GraalCompiler.compileGraph(g, cc, g.method(), providers, backend, backend.getTarget(), null, phaseSuite, OptimisticOptimizations.ALL,
-                            DefaultProfilingInfo.get(TriState.UNKNOWN), null, suites, true, new CompilationResult(), CompilationResultBuilderFactory.Default);
-            InstalledCode installedCode;
-            try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache(), g.method())) {
-                installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null);
-            }
-
-            return installedCode;
-        } catch (SecurityException e) {
-            throw GraalInternalError.shouldNotReachHere("Installation of GNFI Callstub failed.");
-        }
-    }
-}
--- a/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/util/NativeCallStubGraphBuilder.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,271 +0,0 @@
-/*
- * Copyright (c) 2014, 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.nfi.hotspot.amd64.util;
-
-import java.util.*;
-
-import sun.misc.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.nfi.hotspot.amd64.*;
-import com.oracle.graal.nfi.hotspot.amd64.node.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.word.phases.*;
-
-/**
- * Utility that creates a Graal graph. The graph represents the native call stub for a foreign
- * target function.
- * 
- */
-public class NativeCallStubGraphBuilder {
-
-    private static final ResolvedJavaType integerJavaType = HotSpotResolvedObjectType.fromClass(Integer.class);
-    private static final ResolvedJavaField[] integerInstanceFields = integerJavaType.getInstanceFields(false);
-    private static final ResolvedJavaField integerValueField = getValueField(integerInstanceFields);
-
-    private static final ResolvedJavaType longJavaType = HotSpotResolvedObjectType.fromClass(Long.class);
-    private static final ResolvedJavaField[] longInstanceFields = longJavaType.getInstanceFields(false);
-    private static final ResolvedJavaField longValueField = getValueField(longInstanceFields);
-
-    private static final ResolvedJavaType charJavaType = HotSpotResolvedObjectType.fromClass(Character.class);
-    private static final ResolvedJavaField[] charInstanceFields = charJavaType.getInstanceFields(false);
-    private static final ResolvedJavaField charValueField = getValueField(charInstanceFields);
-
-    private static final ResolvedJavaType byteJavaType = HotSpotResolvedObjectType.fromClass(Byte.class);
-    private static final ResolvedJavaField[] byteInstanceFields = byteJavaType.getInstanceFields(false);
-    private static final ResolvedJavaField byteValueField = getValueField(byteInstanceFields);
-
-    private static final ResolvedJavaType floatJavaType = HotSpotResolvedObjectType.fromClass(Float.class);
-    private static final ResolvedJavaField[] floatInstanceFields = floatJavaType.getInstanceFields(false);
-    private static final ResolvedJavaField floatValueField = getValueField(floatInstanceFields);
-
-    private static final ResolvedJavaType doubleJavaType = HotSpotResolvedObjectType.fromClass(Double.class);
-    private static final ResolvedJavaField[] doubleInstanceFields = doubleJavaType.getInstanceFields(false);
-    private static final ResolvedJavaField doubleValueField = getValueField(doubleInstanceFields);
-
-    private static ResolvedJavaField getValueField(ResolvedJavaField[] fields) {
-        for (ResolvedJavaField field : fields) {
-            if (field.getName().equals("value")) {
-                return field;
-            }
-        }
-        throw new AssertionError("value field not found!");
-    }
-
-    /**
-     * Creates a Graal graph that represents the call stub for a foreign target function.
-     * 
-     * @param providers the HotSpot providers
-     * @param functionPointer a function pointer that points to the foreign target function
-     * @param returnType the type of the return value
-     * @param argumentTypes the types of the arguments
-     * @return the graph that represents the call stub
-     */
-    public static StructuredGraph getGraph(HotSpotProviders providers, AMD64HotSpotNativeFunctionPointer functionPointer, Class returnType, Class[] argumentTypes) {
-        ResolvedJavaMethod method;
-        try {
-            method = providers.getMetaAccess().lookupJavaMethod(NativeCallStubGraphBuilder.class.getMethod("libCall", Object.class, Object.class, Object.class));
-            StructuredGraph g = new StructuredGraph(method);
-            ParameterNode arg0 = g.unique(new ParameterNode(0, StampFactory.forKind(Kind.Object)));
-            ParameterNode arg1 = g.unique(new ParameterNode(1, StampFactory.forKind(Kind.Object)));
-            ParameterNode arg2 = g.unique(new ParameterNode(2, StampFactory.forKind(Kind.Object)));
-            FrameState frameState = g.add(new FrameState(method, 0, Arrays.asList(new ValueNode[]{arg0, arg1, arg2}), 3, 0, false, false, new ArrayList<MonitorIdNode>(),
-                            new ArrayList<EscapeObjectState>()));
-            g.start().setStateAfter(frameState);
-            List<ValueNode> parameters = new ArrayList<>();
-            FixedWithNextNode fixedWithNext = getParameters(g, arg0, argumentTypes.length, argumentTypes, parameters, providers);
-            Constant functionPointerNode = Constant.forLong(functionPointer.asRawValue());
-
-            ValueNode[] arguments = new ValueNode[parameters.size()];
-
-            for (int i = 0; i < arguments.length; i++) {
-                arguments[i] = parameters.get(i);
-            }
-
-            AMD64RawNativeCallNode callNode = g.add(new AMD64RawNativeCallNode(getKind(returnType), functionPointerNode, arguments));
-
-            if (fixedWithNext == null) {
-                g.start().setNext(callNode);
-            } else {
-                fixedWithNext.setNext(callNode);
-            }
-
-            // box result
-            BoxNode boxedResult;
-            if (callNode.kind() != Kind.Void) {
-                ResolvedJavaType type = getResolvedJavaType(callNode.kind());
-                boxedResult = new BoxNode(callNode, type, callNode.kind());
-            } else {
-                boxedResult = new BoxNode(ConstantNode.forLong(0, g), longJavaType, Kind.Long);
-            }
-
-            // box result:
-            BoxNode boxNode = g.unique(boxedResult);
-
-            ReturnNode returnNode = g.add(new ReturnNode(boxNode));
-            callNode.setNext(returnNode);
-            (new WordTypeRewriterPhase(providers.getMetaAccess(), Kind.Long)).apply(g);
-            return g;
-        } catch (NoSuchMethodException | SecurityException e) {
-            throw GraalInternalError.shouldNotReachHere("Call Stub method not found");
-        }
-    }
-
-    private static FixedWithNextNode getParameters(StructuredGraph g, ParameterNode argumentsArray, int numArgs, Class[] argumentClass, List<ValueNode> args, HotSpotProviders providers) {
-        assert numArgs == argumentClass.length;
-        FixedWithNextNode fixedWithNext = null;
-        for (int i = 0; i < numArgs; i++) {
-            // load boxed array element:
-            LoadIndexedNode boxedElement = g.add(new LoadIndexedNode(argumentsArray, ConstantNode.forInt(i, g), Kind.Object));
-            if (i == 0) {
-                g.start().setNext(boxedElement);
-                fixedWithNext = boxedElement;
-            } else {
-                fixedWithNext.setNext(boxedElement);
-                fixedWithNext = boxedElement;
-            }
-            if (getKind(argumentClass[i]) == Kind.Object) {
-                // array value
-                Kind arrayElementKind = getArrayValuesKind(argumentClass[i]);
-                LocationIdentity locationIdentity = NamedLocationIdentity.getArrayLocation(arrayElementKind);
-                IndexedLocationNode locationNode = IndexedLocationNode.create(locationIdentity, arrayElementKind, HotSpotGraalRuntime.getArrayBaseOffset(arrayElementKind), ConstantNode.forInt(0, g),
-                                g, HotSpotGraalRuntime.getArrayIndexScale(arrayElementKind));
-                ComputeAddressNode arrayAddress = g.unique(new ComputeAddressNode(boxedElement, locationNode, StampFactory.forKind(providers.getCodeCache().getTarget().wordKind)));
-                args.add(arrayAddress);
-            } else {
-                // boxed primitive value
-                LoadFieldNode loadFieldNode = g.add(new LoadFieldNode(boxedElement, getResolvedJavaField(argumentClass[i])));
-                fixedWithNext.setNext(loadFieldNode);
-                fixedWithNext = loadFieldNode;
-                args.add(loadFieldNode);
-            }
-        }
-        return fixedWithNext;
-    }
-
-    public static int getArrayValuesObjectOffset(Class clazz) {
-        if (clazz == int[].class) {
-            return Unsafe.ARRAY_INT_BASE_OFFSET;
-        } else if (clazz == long[].class) {
-            return Unsafe.ARRAY_LONG_BASE_OFFSET;
-        } else if (clazz == char[].class) {
-            return Unsafe.ARRAY_CHAR_BASE_OFFSET;
-        } else if (clazz == byte[].class) {
-            return Unsafe.ARRAY_BYTE_BASE_OFFSET;
-        } else if (clazz == float[].class) {
-            return Unsafe.ARRAY_FLOAT_BASE_OFFSET;
-        } else if (clazz == double[].class) {
-            return Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
-        } else {
-            throw new IllegalArgumentException("Array Type not supported: " + clazz);
-        }
-    }
-
-    public static Kind getArrayValuesKind(Class clazz) {
-        if (clazz == int[].class) {
-            return Kind.Int;
-        } else if (clazz == long[].class) {
-            return Kind.Long;
-        } else if (clazz == char[].class) {
-            return Kind.Char;
-        } else if (clazz == byte[].class) {
-            return Kind.Byte;
-        } else if (clazz == float[].class) {
-            return Kind.Float;
-        } else if (clazz == double[].class) {
-            return Kind.Double;
-        } else {
-            throw new IllegalArgumentException("Array Type not supported: " + clazz);
-        }
-    }
-
-    private static Kind getKind(Class clazz) {
-        if (clazz == int.class || clazz == Integer.class) {
-            return Kind.Int;
-        } else if (clazz == long.class || clazz == Long.class) {
-            return Kind.Long;
-        } else if (clazz == char.class || clazz == Character.class) {
-            return Kind.Char;
-        } else if (clazz == byte.class || clazz == Byte.class) {
-            return Kind.Byte;
-        } else if (clazz == float.class || clazz == Float.class) {
-            return Kind.Float;
-        } else if (clazz == double.class || clazz == Double.class) {
-            return Kind.Double;
-        } else if (clazz == int[].class || clazz == long[].class || clazz == char[].class || clazz == byte[].class || clazz == float[].class || clazz == double[].class) {
-            return Kind.Object;
-        } else if (clazz == void.class) {
-            return Kind.Void;
-        } else {
-            throw new IllegalArgumentException("Type not supported: " + clazz);
-        }
-    }
-
-    private static ResolvedJavaField getResolvedJavaField(Class containerClass) {
-        if (containerClass == int.class || containerClass == Integer.class) {
-            return integerValueField;
-        } else if (containerClass == long.class || containerClass == Long.class) {
-            return longValueField;
-        } else if (containerClass == char.class || containerClass == Character.class) {
-            return charValueField;
-        } else if (containerClass == byte.class || containerClass == Byte.class) {
-            return byteValueField;
-        } else if (containerClass == float.class || containerClass == Float.class) {
-            return floatValueField;
-        } else if (containerClass == double.class || containerClass == Double.class) {
-            return doubleValueField;
-        } else {
-            throw new IllegalArgumentException("Type not supported: " + containerClass);
-        }
-    }
-
-    private static ResolvedJavaType getResolvedJavaType(Kind kind) {
-        if (kind == Kind.Int) {
-            return integerJavaType;
-        } else if (kind == Kind.Long) {
-            return longJavaType;
-        } else if (kind == Kind.Char) {
-            return charJavaType;
-        } else if (kind == Kind.Byte) {
-            return byteJavaType;
-        } else if (kind == Kind.Float) {
-            return floatJavaType;
-        } else if (kind == Kind.Double) {
-            return doubleJavaType;
-        } else {
-            throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    @SuppressWarnings("unused")
-    public static Object libCall(Object argLoc, Object unused1, Object unused2) {
-        throw GraalInternalError.shouldNotReachHere("GNFI Callstub method must not be called!");
-    }
-}
--- a/graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/LibCallTest.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2013, 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.nfi.test;
-
-import java.lang.reflect.*;
-
-import sun.misc.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.runtime.*;
-
-public class LibCallTest {
-
-    protected static final Unsafe unsafe = getUnsafe();
-    public final RuntimeProvider runtimeProvider;
-    public final NativeFunctionInterface ffi;
-
-    public LibCallTest() {
-        this.runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class);
-        if (runtimeProvider.getHostBackend() instanceof HostBackend) {
-            ffi = ((HostBackend) runtimeProvider.getHostBackend()).getNativeFunctionInterface();
-        } else {
-            throw GraalInternalError.shouldNotReachHere("Cannot initialize GNFI - backend is not a HostBackend");
-        }
-    }
-
-    protected long getDouble(double val) {
-        Long d = unsafe.allocateMemory(8);
-        unsafe.putDouble(d, val);
-        return d;
-    }
-
-    protected long getLong(long val) {
-        Long d = unsafe.allocateMemory(8);
-        unsafe.putLong(d, val);
-        return d;
-    }
-
-    protected long getInt(int val) {
-        Long d = unsafe.allocateMemory(4);
-        unsafe.putInt(d, val);
-        return d;
-    }
-
-    protected void free(long p) {
-        unsafe.freeMemory(p);
-    }
-
-    private static Unsafe getUnsafe() {
-        try {
-            return Unsafe.getUnsafe();
-        } catch (SecurityException e) {
-        }
-        try {
-            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
-            theUnsafeInstance.setAccessible(true);
-            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
-        } catch (Exception e) {
-            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
-        }
-    }
-
-}
--- a/graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/MathLibCallTest.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2013, 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.nfi.test;
-
-import org.junit.*;
-
-import com.oracle.graal.api.code.*;
-
-public class MathLibCallTest extends LibCallTest {
-
-    private final Object[] args = new Object[]{Double.doubleToLongBits(3), Double.doubleToLongBits(5.5)};
-    private final NativeFunctionHandle handle = ffi.getFunctionHandle("pow", double.class, new Class[]{double.class, double.class});
-
-    @Test
-    public void powTest() {
-        double result = (double) handle.call(args);
-        Assert.assertEquals(Math.pow(3, 5.5), result, 0);
-    }
-
-    @Test
-    public void compilePowTest() {
-        double result = 0;
-        for (int i = 0; i < 100000; i++) {
-            result = callPow();
-        }
-        Assert.assertEquals(Math.pow(3, 5.5), result, 0);
-
-    }
-
-    private double callPow() {
-        return (double) handle.call(args);
-    }
-}
--- a/graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/StdLibCallTest.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2013, 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.nfi.test;
-
-import org.junit.*;
-
-import com.oracle.graal.api.code.*;
-
-public class StdLibCallTest extends LibCallTest {
-
-    private static void copyString(long pointer, String s) {
-        for (int i = 0; i < s.length(); i++) {
-            unsafe.putByte(pointer + i, (byte) s.charAt(i));
-        }
-        unsafe.putByte(pointer + s.length(), (byte) '\0');
-    }
-
-    private static void checkString(long pointer, String s) {
-        for (int i = 0; i < s.length(); i++) {
-            Assert.assertEquals(unsafe.getByte(pointer + i) & 0xFF, (byte) s.charAt(i));
-        }
-        Assert.assertEquals(unsafe.getByte(pointer + s.length()) & 0xFF, (byte) '\0');
-    }
-
-    private static long getBuffer(int length) {
-        return unsafe.allocateMemory(length);
-    }
-
-    @Test
-    public void mallocTest() {
-        String string = "GRAAL";
-        int stringLength = string.length() + 1;
-
-        Object[] args = new Object[]{1};
-        args[0] = stringLength;
-        NativeFunctionHandle mallocHandle = ffi.getFunctionHandle("malloc", long.class, new Class[]{int.class});
-
-        long p = (long) mallocHandle.call(args);
-        copyString(p, string);
-
-        long buffer = getBuffer(stringLength);
-        NativeFunctionHandle putsHandle = ffi.getFunctionHandle("snprintf", int.class, new Class[]{long.class, int.class, long.class});
-        Object[] args2 = new Object[]{buffer, stringLength, p};
-        int result = (int) putsHandle.call(args2);
-        Assert.assertTrue(0 < result);
-        checkString(p, string);
-        checkString(buffer, string);
-
-        NativeFunctionHandle freeHandle = ffi.getFunctionHandle("free", void.class, new Class[]{long.class});
-        freeHandle.call(args2);
-    }
-
-    @Test
-    public void printfSimpleTest() {
-        long str = unsafe.allocateMemory(8);
-        copyString(str, "AB %f%f");
-
-        String referenceString = "AB 1.0000001.000000";
-        int referenceStringLenght = referenceString.length() + 1;
-
-        long buffer = getBuffer(referenceStringLenght);
-
-        Object[] args = new Object[]{buffer, referenceStringLenght, str, Double.doubleToRawLongBits(1.0), Double.doubleToRawLongBits(1.0)};
-        NativeFunctionHandle printfHandle = ffi.getFunctionHandle("snprintf", int.class, new Class[]{long.class, int.class, long.class, double.class, double.class});
-
-        int result = (int) printfHandle.call(args);
-
-        checkString(buffer, referenceString);
-        Assert.assertTrue(0 < result);
-    }
-
-    @Test
-    public void printfTest() {
-        long str = unsafe.allocateMemory(25);
-        int[] val = new int[12];
-        for (int i = 0; i < 12; i++) {
-            unsafe.putByte(str + 2 * i, (byte) '%');
-            unsafe.putByte(str + 2 * i + 1, (byte) 'i');
-            val[i] = i;
-        }
-        unsafe.putByte(str + 24, (byte) '\0');
-
-        String referenceString = "01234567891011";
-        int referenceStringLenght = referenceString.length() + 1;
-
-        long buffer = getBuffer(referenceStringLenght);
-
-        Object[] args = new Object[]{buffer, referenceStringLenght, str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11]};
-        NativeFunctionHandle printfHandle = ffi.getFunctionHandle("snprintf", int.class, new Class[]{long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class,
-                        int.class, int.class, int.class, int.class, int.class, int.class, int.class});
-
-        int result = (int) printfHandle.call(args);
-        checkString(buffer, referenceString);
-        Assert.assertTrue(0 < result);
-    }
-
-    @Test
-    public void printfTest2() {
-        long str = unsafe.allocateMemory(49);
-        int[] val = new int[12];
-        for (int i = 0; i < 12; i++) {
-            unsafe.putByte(str + 2 * i, (byte) '%');
-            unsafe.putByte(str + 2 * i + 1, (byte) 'i');
-            val[i] = i;
-        }
-        double[] dval = new double[12];
-        for (int i = 12; i < 24; i++) {
-            unsafe.putByte(str + 2 * i, (byte) '%');
-            unsafe.putByte(str + 2 * i + 1, (byte) 'f');
-            dval[i - 12] = i + 0.5;
-        }
-        unsafe.putByte(str + 48, (byte) '\0');
-
-        String referenceString = "0123456789101112.50000013.50000014.50000015.50000016.50000017.50000018.50000019.50000020.500000" + "21.50000022.50000023.500000";
-        int referenceStringLenght = referenceString.length() + 1;
-
-        long buffer = getBuffer(referenceStringLenght);
-
-        Object[] args = new Object[]{buffer, referenceStringLenght, str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], dval[0], dval[1], dval[2],
-                        dval[3], dval[4], dval[5], dval[6], dval[7], dval[8], dval[9], dval[10], dval[11]};
-
-        NativeFunctionHandle printfHandle = ffi.getFunctionHandle("snprintf", int.class, new Class[]{long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class,
-                        int.class, int.class, int.class, int.class, int.class, int.class, int.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class,
-                        double.class, double.class, double.class, double.class, double.class});
-
-        int result = (int) printfHandle.call(args);
-        checkString(buffer, referenceString);
-        Assert.assertTrue(0 < result);
-    }
-
-    @Test
-    public void printfTest3() {
-        long str = unsafe.allocateMemory(73);
-        int[] val = new int[12];
-        for (int i = 0; i < 12; i++) {
-            unsafe.putByte(str + 2 * i, (byte) '%');
-            unsafe.putByte(str + 2 * i + 1, (byte) 'i');
-            val[i] = i;
-        }
-        double[] dval = new double[12];
-        for (int i = 12; i < 24; i++) {
-            unsafe.putByte(str + 2 * i, (byte) '%');
-            unsafe.putByte(str + 2 * i + 1, (byte) 'f');
-            dval[i - 12] = i + 0.5;
-        }
-        char[] cval = new char[12];
-        for (int i = 24; i < 36; i++) {
-            unsafe.putByte(str + 2 * i, (byte) '%');
-            unsafe.putByte(str + 2 * i + 1, (byte) 'c');
-            cval[i - 24] = (char) ('a' + (i - 24));
-        }
-        unsafe.putByte(str + 72, (byte) '\0');
-
-        String referenceString = "0123456789101112.50000013.50000014.50000015.50000016.50000017.50000018.50000019.50000020.50000021.50000022.50000023.500000abcdefghijkl";
-        int referenceStringLenght = referenceString.length() + 1;
-
-        long buffer = getBuffer(referenceStringLenght);
-
-        Object[] args = new Object[]{buffer, referenceStringLenght, str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], dval[0], dval[1], dval[2],
-                        dval[3], dval[4], dval[5], dval[6], dval[7], dval[8], dval[9], dval[10], dval[11], cval[0], cval[1], cval[2], cval[3], cval[4], cval[5], cval[6], cval[7], cval[8], cval[9],
-                        cval[10], cval[11]};
-
-        NativeFunctionHandle printfHandle = ffi.getFunctionHandle("snprintf", int.class, new Class[]{long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class,
-                        int.class, int.class, int.class, int.class, int.class, int.class, int.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class,
-                        double.class, double.class, double.class, double.class, double.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class,
-                        char.class, char.class, char.class, char.class});
-
-        int result = (int) printfHandle.call(args);
-        checkString(buffer, referenceString);
-        Assert.assertTrue(0 < result);
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -36,7 +36,7 @@
  * loop.
  */
 @NodeInfo(nameTemplate = "{p#type/s}Proxy")
-public class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, ValueProxy, GuardingNode {
+public class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, ValueAndStampProxy, GuardingNode {
 
     @Input(notDataflow = true) private AbstractBeginNode proxyPoint;
     @Input private ValueNode value;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -35,37 +35,16 @@
 
     public static IntegerAddNode add(StructuredGraph graph, ValueNode v1, ValueNode v2) {
         assert v1.kind() == v2.kind();
-        switch (v1.kind()) {
-            case Int:
-                return graph.unique(new IntegerAddNode(Kind.Int, v1, v2));
-            case Long:
-                return graph.unique(new IntegerAddNode(Kind.Long, v1, v2));
-            default:
-                throw ValueNodeUtil.shouldNotReachHere();
-        }
+        return graph.unique(new IntegerAddNode(v1.kind(), v1, v2));
     }
 
     public static IntegerMulNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2) {
         assert v1.kind() == v2.kind();
-        switch (v1.kind()) {
-            case Int:
-                return graph.unique(new IntegerMulNode(Kind.Int, v1, v2));
-            case Long:
-                return graph.unique(new IntegerMulNode(Kind.Long, v1, v2));
-            default:
-                throw ValueNodeUtil.shouldNotReachHere();
-        }
+        return graph.unique(new IntegerMulNode(v1.kind(), v1, v2));
     }
 
     public static IntegerSubNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2) {
         assert v1.kind() == v2.kind();
-        switch (v1.kind()) {
-            case Int:
-                return graph.unique(new IntegerSubNode(Kind.Int, v1, v2));
-            case Long:
-                return graph.unique(new IntegerSubNode(Kind.Long, v1, v2));
-            default:
-                throw ValueNodeUtil.shouldNotReachHere();
-        }
+        return graph.unique(new IntegerSubNode(v1.kind(), v1, v2));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -71,7 +71,7 @@
     public static ValueNode canonicalizeRead(ValueNode read, LocationNode location, ValueNode object, CanonicalizerTool tool, boolean compressible) {
         MetaAccessProvider metaAccess = tool.getMetaAccess();
         if (read.usages().isEmpty()) {
-            // Read without usages can be savely removed.
+            // Read without usages can be safely removed.
             return null;
         }
         if (tool.canonicalizeReads() && metaAccess != null && object != null && object.isConstant()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -31,7 +31,7 @@
 /**
  * The {@code NewMultiArrayNode} represents an allocation of a multi-dimensional object array.
  */
-public final class NewMultiArrayNode extends DeoptimizingFixedWithNextNode implements Lowerable {
+public class NewMultiArrayNode extends DeoptimizingFixedWithNextNode implements Lowerable, ArrayLengthProvider {
 
     @Input private final NodeInputList<ValueNode> dimensions;
     private final ResolvedJavaType type;
@@ -74,4 +74,8 @@
     public boolean canDeoptimize() {
         return true;
     }
+
+    public ValueNode length() {
+        return dimension(0);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ValueAndStampProxy.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.spi;
+
+/**
+ * This interface marks nodes whose result is the same as one of their inputs, and whose stamp is
+ * the same as one of their inputs.
+ * 
+ * For some algorithms it is necessary or advantageous to see through these proxies.
+ */
+public interface ValueAndStampProxy extends ValueProxy {
+}
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java	Mon Feb 17 13:48:41 2014 +0100
@@ -157,6 +157,7 @@
 
             boolean needPrivateFieldAccessor = false;
             int i = 0;
+            Collections.sort(info.options);
             for (OptionInfo option : info.options) {
                 String optionValue;
                 if (option.field.getModifiers().contains(Modifier.PRIVATE)) {
@@ -223,7 +224,7 @@
         }
     }
 
-    static class OptionInfo {
+    static class OptionInfo implements Comparable<OptionInfo> {
 
         final String name;
         final String help;
@@ -240,6 +241,11 @@
         }
 
         @Override
+        public int compareTo(OptionInfo other) {
+            return name.compareTo(other.name);
+        }
+
+        @Override
         public String toString() {
             return declaringClass + "." + field;
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Mon Feb 17 13:48:41 2014 +0100
@@ -428,6 +428,10 @@
                 return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "intrinsic");
             }
 
+            if (info.shouldInline()) {
+                return InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "forced inlining");
+            }
+
             double inliningBonus = getInliningBonus(info);
             int nodes = determineNodeCount(info);
             int lowLevelGraphSize = previousLowLevelGraphSize(info);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Feb 17 13:48:41 2014 +0100
@@ -295,6 +295,8 @@
          * Try to make the call static bindable to avoid interface and virtual method calls.
          */
         void tryToDevirtualizeInvoke(MetaAccessProvider metaAccess, Assumptions assumptions);
+
+        boolean shouldInline();
     }
 
     public abstract static class AbstractInlineInfo implements InlineInfo {
@@ -411,6 +413,10 @@
             assert index == 0;
             this.inlineableElement = inlineableElement;
         }
+
+        public boolean shouldInline() {
+            return concrete.shouldBeInlined();
+        }
     }
 
     /**
@@ -497,6 +503,10 @@
         public String toString() {
             return "type-checked with type " + type.getName() + " and method " + MetaUtil.format("%H.%n(%p):%r", concrete);
         }
+
+        public boolean shouldInline() {
+            return concrete.shouldBeInlined();
+        }
     }
 
     /**
@@ -592,6 +602,15 @@
             }
         }
 
+        public boolean shouldInline() {
+            for (ResolvedJavaMethod method : concretes) {
+                if (method.shouldBeInlined()) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
         private boolean hasSingleMethod() {
             return concretes.size() == 1 && !shouldFallbackToInvoke();
         }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Mon Feb 17 13:48:41 2014 +0100
@@ -232,6 +232,9 @@
     @Option(help = "Try to avoid emitting code where patching is required")
     public static final OptionValue<Boolean> ImmutableCode = new OptionValue<>(false);
 
+    @Option(help = "")
+    public static final OptionValue<Boolean> CallArrayCopy = new OptionValue<>(true);
+
     // Runtime settings
     @Option(help = "")
     public static final OptionValue<Boolean> SupportJsrBytecodes = new OptionValue<>(true);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013, 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.phases.graph;
+
+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.*;
+
+public class InferStamps {
+
+    /**
+     * Infer the stamps for all Object nodes in the graph, to make the stamps as precise as
+     * possible. For example, this propagates the word-type through phi functions. To handle phi
+     * functions at loop headers, the stamp inference is called until a fix point is reached.
+     * <p>
+     * This method can be used when it is needed that stamps are inferred before the first run of
+     * the canonicalizer. For example, word type rewriting must run before the first run of the
+     * canonicalizer because many nodes are not prepared to see the word type during
+     * canonicalization.
+     */
+    public static void inferStamps(StructuredGraph graph) {
+        /*
+         * We want to make the stamps more precise. For cyclic phi functions, this means we have to
+         * ignore the initial stamp because the imprecise stamp would always propagate around the
+         * cycle. We therefore set the stamp to an illegal stamp, which is automatically ignored
+         * when the phi function performs the "meet" operator on its input stamps.
+         */
+        for (Node n : graph.getNodes()) {
+            if (n instanceof PhiNode || n instanceof ValueAndStampProxy) {
+                ValueNode node = (ValueNode) n;
+                if (node.kind() == Kind.Object) {
+                    assert !(node.stamp() instanceof IllegalStamp) : "We assume all Phi and Proxy stamps are legal before the analysis";
+                    node.setStamp(StampFactory.illegal(node.kind()));
+                }
+            }
+        }
+
+        boolean stampChanged;
+        do {
+            stampChanged = false;
+            /*
+             * We could use GraphOrder.forwardGraph() to process the nodes in a defined order and
+             * propagate long def-use chains in fewer iterations. However, measurements showed that
+             * we have few iterations anyway, and the overhead of computing the order is much higher
+             * than the benefit.
+             */
+            for (Node n : graph.getNodes()) {
+                if (n instanceof ValueNode) {
+                    ValueNode node = (ValueNode) n;
+                    if (node.kind() == Kind.Object) {
+                        stampChanged |= node.inferStamp();
+                    }
+                }
+            }
+        } while (stampChanged);
+
+        /*
+         * Check that all the illegal stamps we introduced above are correctly replaced with real
+         * stamps again.
+         */
+        assert checkNoIllegalStamp(graph);
+    }
+
+    private static boolean checkNoIllegalStamp(StructuredGraph graph) {
+        for (Node n : graph.getNodes()) {
+            if (n instanceof PhiNode || n instanceof ValueAndStampProxy) {
+                ValueNode node = (ValueNode) n;
+                assert !(node.stamp() instanceof IllegalStamp) : "Stamp is illegal after analysis. This is not necessarily an error, but a condition that we want to investigate (and then maybe relax or remove the assertion).";
+            }
+        }
+        return true;
+    }
+
+}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Mon Feb 17 13:48:41 2014 +0100
@@ -526,8 +526,10 @@
                 ParameterNode[] params = new ParameterNode[length];
                 Stamp stamp = varargs.stamp;
                 for (int j = 0; j < length; j++) {
-                    assert (parameterCount & 0xFFFF) == parameterCount;
-                    int idx = i << 16 | j;
+                    // Use a decimal friendly numbering make it more obvious how values map
+                    assert parameterCount < 10000;
+                    int idx = (i + 1) * 10000 + j;
+                    assert idx >= parameterCount : "collision in parameter numbering";
                     ParameterNode local = snippetCopy.unique(new ParameterNode(idx, stamp));
                     params[j] = local;
                 }
@@ -542,6 +544,11 @@
                         LoadSnippetVarargParameterNode loadSnippetParameter = snippetCopy.add(new LoadSnippetVarargParameterNode(params, loadIndexed.index(), loadIndexed.stamp()));
                         snippetCopy.replaceFixedWithFixed(loadIndexed, loadSnippetParameter);
                         Debug.dump(snippetCopy, "After replacing %s", loadIndexed);
+                    } else if (usage instanceof StoreIndexedNode) {
+                        // The template lowering doesn't really treat this as an array so you can't
+                        // store back into the varargs. Allocate your own array if you really need
+                        // this and EA should eliminate it.
+                        throw new GraalInternalError("Can't store into VarargsParameter array");
                     }
                 }
             } else {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -66,6 +66,11 @@
         return index;
     }
 
+    @NodeIntrinsic
+    public static int scan(int v) {
+        return scan(v & 0xFFFFFFFFL);
+    }
+
     @Override
     public void generate(LIRGenerator gen) {
         Variable result = gen.newVariable(Kind.Int);
--- a/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java	Mon Feb 17 13:48:41 2014 +0100
@@ -81,7 +81,7 @@
 
     public void setInstrumentedMethod(ResolvedJavaMethod method) {
         HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method;
-        hsMethod.setDontInline();
+        hsMethod.setNotInlineable();
     }
 
     public String getArchitecture() {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java	Mon Feb 17 13:48:41 2014 +0100
@@ -73,13 +73,10 @@
     }
 
     public RootCallTarget createCallTarget(RootNode rootNode) {
-        if (!acceptForCompilation(rootNode)) {
-            return new UnoptimizedCallTarget(rootNode);
-        }
         if (truffleCompiler == null) {
             truffleCompiler = new TruffleCompilerImpl();
         }
-        return new OptimizedCallTarget(rootNode, truffleCompiler, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue());
+        return new OptimizedCallTarget(rootNode, truffleCompiler, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue(), acceptForCompilation(rootNode));
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Feb 17 13:48:41 2014 +0100
@@ -38,7 +38,7 @@
 /**
  * Call target that is optimized by Graal upon surpassing a specific invocation threshold.
  */
-public final class OptimizedCallTarget extends DefaultCallTarget implements FrameFactory, LoopCountReceiver, ReplaceObserver {
+public final class OptimizedCallTarget extends DefaultCallTarget implements LoopCountReceiver, ReplaceObserver {
 
     private static final PrintStream OUT = TTY.out().out();
 
@@ -52,7 +52,7 @@
     private int callCount;
     private SpeculationLog speculationLog = new SpeculationLog();
 
-    protected OptimizedCallTarget(RootNode rootNode, TruffleCompiler compiler, int invokeCounter, int compilationThreshold) {
+    OptimizedCallTarget(RootNode rootNode, TruffleCompiler compiler, int invokeCounter, int compilationThreshold, boolean compilationEnabled) {
         super(rootNode);
         this.compiler = compiler;
         this.compilationProfile = new CompilationProfile(compilationThreshold, invokeCounter, rootNode.toString());
@@ -62,7 +62,7 @@
         } else {
             compilationPolicy = new DefaultCompilationPolicy();
         }
-        this.compilationEnabled = true;
+        this.compilationEnabled = compilationEnabled;
 
         if (TruffleCallTargetProfiling.getValue()) {
             registerCallTarget(this);
@@ -79,13 +79,7 @@
 
     private Object callHelper(PackedFrame caller, Arguments args) {
         if (installedCode != null && installedCode.isValid()) {
-            TruffleRuntime runtime = Truffle.getRuntime();
-            if (runtime instanceof GraalTruffleRuntime) {
-                if (TraceTruffleCompilation.getValue()) {
-                    OUT.println("[truffle] reinstall OptimizedCallTarget.call code with frame prolog shortcut.");
-                }
-                GraalTruffleRuntime.installOptimizedCallTargetCallMethod();
-            }
+            reinstallCallMethodShortcut();
         }
         if (TruffleCallTargetProfiling.getValue()) {
             callCount++;
@@ -101,6 +95,13 @@
         }
     }
 
+    private static void reinstallCallMethodShortcut() {
+        if (TraceTruffleCompilation.getValue()) {
+            OUT.println("[truffle] reinstall OptimizedCallTarget.call code with frame prolog shortcut.");
+        }
+        GraalTruffleRuntime.installOptimizedCallTargetCallMethod();
+    }
+
     public CompilationProfile getCompilationProfile() {
         return compilationProfile;
     }
@@ -117,7 +118,7 @@
             installedCode = null;
             compilationProfile.reportInvalidated();
             if (TraceTruffleCompilation.getValue()) {
-                OUT.printf("[truffle] invalidated %-48s |Inv# %d                                     |Replace# %d\n", getRootNode(), compilationProfile.getInvalidationCount(),
+                OUT.printf("[truffle] invalidated %-48s %08x |InvalidationCount %2d |ReplaceCount %3d\n", getRootNode(), getRootNode().hashCode(), compilationProfile.getInvalidationCount(),
                                 compilationProfile.getNodeReplaceCount());
             }
         }
@@ -221,11 +222,6 @@
     }
 
     @Override
-    public VirtualFrame create(FrameDescriptor descriptor, PackedFrame caller, Arguments args) {
-        return createFrame(descriptor, caller, args);
-    }
-
-    @Override
     public void reportLoopCount(int count) {
         compilationProfile.reportLoopCount(count);
     }
@@ -236,6 +232,10 @@
         invalidate();
     }
 
+    public SpeculationLog getSpeculationLog() {
+        return speculationLog;
+    }
+
     private static void printProfiling() {
         List<OptimizedCallTarget> sortedCallTargets = new ArrayList<>(OptimizedCallTarget.callTargets.keySet());
         Collections.sort(sortedCallTargets, new Comparator<OptimizedCallTarget>() {
@@ -306,8 +306,4 @@
             });
         }
     }
-
-    public SpeculationLog getSpeculationLog() {
-        return speculationLog;
-    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Mon Feb 17 13:48:41 2014 +0100
@@ -208,6 +208,7 @@
                         if (TraceTruffleExpansion.getValue()) {
                             expansionLogger.preExpand(methodCallTargetNode, inlineGraph);
                         }
+                        List<Node> invokeUsages = methodCallTargetNode.invoke().asNode().usages().snapshot();
                         Map<Node, Node> inlined = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false);
                         if (TraceTruffleExpansion.getValue()) {
                             expansionLogger.postExpand(inlined);
@@ -216,7 +217,7 @@
                             int nodeCountAfter = graph.getNodeCount();
                             Debug.dump(graph, "After inlining %s %+d (%d)", methodCallTargetNode.targetMethod().toString(), nodeCountAfter - nodeCountBefore, nodeCountAfter);
                         }
-                        canonicalizer.applyIncremental(graph, phaseContext, mark);
+                        canonicalizer.applyIncremental(graph, phaseContext, invokeUsages, mark);
                         changed = true;
                     }
                 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Mon Feb 17 13:48:41 2014 +0100
@@ -169,13 +169,18 @@
         if (TraceTruffleCompilation.getValue()) {
             int nodeCountTruffle = NodeUtil.countNodes(compilable.getRootNode(), null, true);
             byte[] code = compiledMethod.getCode();
-            OUT.printf("[truffle] optimized %-50s %x |Nodes %7d |Time %5.0f(%4.0f+%-4.0f)ms |Nodes %5d/%5d |CodeSize %d\n", compilable.getRootNode(), compilable.hashCode(), nodeCountTruffle,
+            OUT.printf("[truffle] optimized %-50s %08x |Tree %8d |Time %5.0f(%4.0f+%-4.0f)ms |Graph %5d/%5d |CodeSize %6d @ %s\n", compilable.getRootNode(), compilable.hashCode(), nodeCountTruffle,
                             (timeCompilationFinished - timeCompilationStarted) / 1e6, (timePartialEvaluationFinished - timeCompilationStarted) / 1e6,
-                            (timeCompilationFinished - timePartialEvaluationFinished) / 1e6, nodeCountPartialEval, nodeCountLowered, code != null ? code.length : 0);
+                            (timeCompilationFinished - timePartialEvaluationFinished) / 1e6, nodeCountPartialEval, nodeCountLowered, code != null ? code.length : 0,
+                            formatSourceSection(compilable.getRootNode().getSourceSection()));
         }
         return compiledMethod;
     }
 
+    private static String formatSourceSection(SourceSection sourceSection) {
+        return sourceSection != null ? sourceSection.toString() : "n/a";
+    }
+
     private void printInlineTree(RootNode rootNode) {
         OUT.println();
         OUT.println("Inlining tree for: " + rootNode);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Feb 17 13:48:41 2014 +0100
@@ -56,7 +56,7 @@
     @Option(help = "")
     public static final OptionValue<Boolean> TruffleFunctionInlining = new OptionValue<>(true);
     @Option(help = "")
-    public static final OptionValue<Integer> TruffleGraphMaxNodes = new OptionValue<>(25000);
+    public static final OptionValue<Integer> TruffleGraphMaxNodes = new OptionValue<>(30000);
     @Option(help = "")
     public static final OptionValue<Integer> TruffleInliningMaxRecursiveDepth = new OptionValue<>(2);
     @Option(help = "")
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningImpl.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningImpl.java	Mon Feb 17 13:48:41 2014 +0100
@@ -115,7 +115,8 @@
     private static void printCallSiteInfo(InliningPolicy policy, InlinableCallSiteInfo callSite, String msg) {
         String calls = String.format("%4s/%4s", callSite.getCallCount(), policy.callerInvocationCount);
         String nodes = String.format("%3s/%3s", callSite.getInlineNodeCount(), policy.callerNodeCount);
-        OUT.printf("[truffle] %-9s %-50s |Nodes %6s |Calls %6s %7.3f |%s\n", msg, callSite.getCallNode(), nodes, calls, policy.metric(callSite), callSite.getCallNode().getCallTarget());
+        CallTarget inlined = callSite.getCallNode().getCallTarget();
+        OUT.printf("[truffle] %-9s %-50s %08x |Tree %8s |Calls %6s %7.3f @ %s\n", msg, inlined, inlined.hashCode(), nodes, calls, policy.metric(callSite), callSite.getCallNode());
     }
 
     private static final class InliningPolicy {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Mon Feb 17 13:48:41 2014 +0100
@@ -58,7 +58,6 @@
         truffleReplacements.registerSubstitutions(FrameWithoutBoxingSubstitutions.class);
         truffleReplacements.registerSubstitutions(OptimizedAssumptionSubstitutions.class);
         truffleReplacements.registerSubstitutions(OptimizedCallTargetSubstitutions.class);
-        truffleReplacements.registerSubstitutions(DefaultCallTargetSubstitutions.class);
 
         return truffleReplacements;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/UnoptimizedCallTarget.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2013, 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.truffle;
-
-import com.oracle.truffle.api.impl.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Call target that is not optimized by Graal upon surpassing a specific invocation threshold.
- */
-public final class UnoptimizedCallTarget extends DefaultCallTarget {
-
-    protected UnoptimizedCallTarget(RootNode rootNode) {
-        super(rootNode);
-    }
-}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -74,7 +74,7 @@
     @Override
     public void generate(LIRGenerator generator) {
         generator.setResult(this, generateArithmetic(generator));
-        generator.emitOverflowCheckBranch(generator.getLIRBlock(getNext()), generator.getLIRBlock(getOverflowSuccessor()));
+        generator.emitOverflowCheckBranch(generator.getLIRBlock(getOverflowSuccessor()), generator.getLIRBlock(getNext()), probability(getOverflowSuccessor()));
     }
 
     protected abstract Value generateArithmetic(LIRGeneratorTool generator);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, 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.truffle.nodes.typesystem;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.truffle.api.*;
+
+/**
+ * Load of a final value from a location specified as an offset relative to an object.
+ * 
+ * Substitution for method {@link CompilerDirectives#unsafeGetFinalObject} and friends.
+ */
+public class CustomizedUnsafeLoadFinalNode extends FixedWithNextNode implements Canonicalizable, Virtualizable, Lowerable {
+    @Input private ValueNode object;
+    @Input private ValueNode offset;
+    @Input private ValueNode condition;
+    @Input private ValueNode location;
+    private final Kind accessKind;
+
+    public CustomizedUnsafeLoadFinalNode(ValueNode object, ValueNode offset, ValueNode condition, ValueNode location, Kind accessKind) {
+        super(StampFactory.forKind(accessKind.getStackKind()));
+        this.object = object;
+        this.offset = offset;
+        this.condition = condition;
+        this.location = location;
+        this.accessKind = accessKind;
+    }
+
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        if (object.isConstant() && !object.isNullConstant() && offset.isConstant()) {
+            Constant constant = tool.getConstantReflection().readUnsafeConstant(accessKind, object.asConstant().asObject(), offset.asConstant().asLong(), accessKind == Kind.Object);
+            return ConstantNode.forConstant(constant, tool.getMetaAccess(), graph());
+        }
+        return this;
+    }
+
+    /**
+     * @see UnsafeLoadNode#virtualize(VirtualizerTool)
+     */
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        State state = tool.getObjectState(object);
+        if (state != null && state.getState() == EscapeState.Virtual) {
+            ValueNode offsetValue = tool.getReplacedValue(offset);
+            if (offsetValue.isConstant()) {
+                long constantOffset = offsetValue.asConstant().asLong();
+                int entryIndex = state.getVirtualObject().entryIndexForOffset(constantOffset);
+                if (entryIndex != -1) {
+                    ValueNode entry = state.getEntry(entryIndex);
+                    if (entry.kind() == kind() || state.getVirtualObject().entryKind(entryIndex) == accessKind) {
+                        tool.replaceWith(entry);
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        CompareNode compare = CompareNode.createCompareNode(graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, graph()));
+        Object locationIdentityObject = location.asConstant().asObject();
+        LocationIdentity locationIdentity;
+        if (locationIdentityObject == null) {
+            locationIdentity = LocationIdentity.ANY_LOCATION;
+        } else {
+            locationIdentity = ObjectLocationIdentity.create(locationIdentityObject);
+        }
+        UnsafeLoadNode result = graph().add(new UnsafeLoadNode(object, offset, accessKind, locationIdentity, compare));
+        graph().replaceFixedWithFixed(this, result);
+        result.lower(tool);
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static <T> T load(Object object, long offset, boolean condition, Object locationIdentity, @ConstantNodeParameter Kind kind) {
+        return UnsafeLoadNode.load(object, offset, kind, null);
+    }
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Mon Feb 17 13:48:41 2014 +0100
@@ -91,6 +91,9 @@
     public static native int unsafeGetInt(Object receiver, long offset, boolean condition, Object locationIdentity);
 
     @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true)
+    public static native long unsafeGetLong(Object receiver, long offset, boolean condition, Object locationIdentity);
+
+    @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true)
     public static native float unsafeGetFloat(Object receiver, long offset, boolean condition, Object locationIdentity);
 
     @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true)
@@ -122,4 +125,44 @@
 
     @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true)
     public static native void unsafePutObject(Object receiver, long offset, Object value, Object locationIdentity);
+
+    @MethodSubstitution
+    public static boolean unsafeGetFinalBoolean(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Boolean);
+    }
+
+    @MethodSubstitution
+    public static byte unsafeGetFinalByte(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Byte);
+    }
+
+    @MethodSubstitution
+    public static short unsafeGetFinalShort(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Short);
+    }
+
+    @MethodSubstitution
+    public static int unsafeGetFinalInt(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Int);
+    }
+
+    @MethodSubstitution
+    public static long unsafeGetFinalLong(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Long);
+    }
+
+    @MethodSubstitution
+    public static float unsafeGetFinalFloat(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Float);
+    }
+
+    @MethodSubstitution
+    public static double unsafeGetFinalDouble(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Double);
+    }
+
+    @MethodSubstitution
+    public static Object unsafeGetFinalObject(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Object);
+    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/DefaultCallTargetSubstitutions.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2013, 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.truffle.substitutions;
-
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.truffle.nodes.asserts.*;
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.impl.*;
-
-@ClassSubstitution(DefaultCallTarget.class)
-public class DefaultCallTargetSubstitutions {
-
-    @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false)
-    public static native Object call(DefaultCallTarget target, PackedFrame caller, Arguments args);
-}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java	Mon Feb 17 13:48:41 2014 +0100
@@ -46,10 +46,4 @@
     private static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments args) {
         return NewFrameNode.allocate(descriptor, caller, args);
     }
-
-    @SuppressWarnings("unused")
-    @MethodSubstitution(isStatic = false)
-    private static VirtualFrame create(OptimizedCallTarget target, FrameDescriptor descriptor, PackedFrame caller, Arguments args) {
-        return createFrame(descriptor, caller, args);
-    }
 }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Mon Feb 17 13:48:41 2014 +0100
@@ -36,6 +36,7 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.word.*;
 import com.oracle.graal.word.Word.Opcode;
 import com.oracle.graal.word.Word.Operation;
@@ -63,7 +64,7 @@
 
     @Override
     protected void run(StructuredGraph graph) {
-        inferStamps(graph);
+        InferStamps.inferStamps(graph);
 
         for (Node n : graph.getNodes()) {
             if (n instanceof ValueNode) {
@@ -77,68 +78,6 @@
     }
 
     /**
-     * Infer the stamps for all Object nodes in the graph, to make the stamps as precise as
-     * possible. For example, this propagates the word-type through phi functions. To handle phi
-     * functions at loop headers, the stamp inference is called until a fix point is reached.
-     * <p>
-     * Note that we cannot rely on the normal canonicalizer to propagate stamps: The word type
-     * rewriting must run before the first run of the canonicalizer because many nodes are not
-     * prepared to see the word type during canonicalization.
-     */
-    protected void inferStamps(StructuredGraph graph) {
-        /*
-         * We want to make the stamps more precise. For cyclic phi functions, this means we have to
-         * ignore the initial stamp because the imprecise stamp would always propagate around the
-         * cycle. We therefore set the stamp to an illegal stamp, which is automatically ignored
-         * when the phi function performs the "meet" operator on its input stamps.
-         */
-        for (Node n : graph.getNodes()) {
-            if (n instanceof PhiNode || n instanceof ProxyNode) {
-                ValueNode node = (ValueNode) n;
-                if (node.kind() == Kind.Object) {
-                    assert !(node.stamp() instanceof IllegalStamp) : "We assume all Phi and Proxy stamps are legal before the analysis";
-                    node.setStamp(StampFactory.illegal(node.kind()));
-                }
-            }
-        }
-
-        boolean stampChanged;
-        do {
-            stampChanged = false;
-            /*
-             * We could use GraphOrder.forwardGraph() to process the nodes in a defined order and
-             * propagate long def-use chains in fewer iterations. However, measurements showed that
-             * we have few iterations anyway, and the overhead of computing the order is much higher
-             * than the benefit.
-             */
-            for (Node n : graph.getNodes()) {
-                if (n instanceof ValueNode) {
-                    ValueNode node = (ValueNode) n;
-                    if (node.kind() == Kind.Object) {
-                        stampChanged |= node.inferStamp();
-                    }
-                }
-            }
-        } while (stampChanged);
-
-        /*
-         * Check that all the illegal stamps we introduced above are correctly replaced with real
-         * stamps again.
-         */
-        assert checkNoIllegalStamp(graph);
-    }
-
-    private static boolean checkNoIllegalStamp(StructuredGraph graph) {
-        for (Node n : graph.getNodes()) {
-            if (n instanceof PhiNode || n instanceof ProxyNode) {
-                ValueNode node = (ValueNode) n;
-                assert !(node.stamp() instanceof IllegalStamp) : "Stamp is illegal after analysis. This is not necessarily an error, but a condition that we want to investigate (and then maybe relax or remove the assertion).";
-            }
-        }
-        return true;
-    }
-
-    /**
      * Change the stamp for word nodes from the object stamp ({@link WordBase} or anything extending
      * or implementing that interface) to the primitive word stamp.
      */
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Mon Feb 17 13:48:41 2014 +0100
@@ -32,6 +32,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.word.*;
 import com.oracle.graal.word.Word.Operation;
 
@@ -58,7 +59,7 @@
          * modifies the stamp of nodes, we copy the graph before running the verification.
          */
         StructuredGraph graph = inputGraph.copy();
-        wordAccess.inferStamps(graph);
+        InferStamps.inferStamps(graph);
 
         for (ValueNode node : graph.getNodes().filter(ValueNode.class)) {
             if (!node.recordsUsages()) {
@@ -81,7 +82,6 @@
                 } else if (usage instanceof StoreIndexedNode) {
                     verify(!isWord(node) || ((StoreIndexedNode) usage).array() != node, node, usage, "cannot store to word value");
                     verify(!isWord(node) || ((StoreIndexedNode) usage).index() != node, node, usage, "cannot use word value as index");
-                    verify(!isWord(node) || ((StoreIndexedNode) usage).value() != node, node, usage, "cannot store word value to array");
                 } else if (usage instanceof MethodCallTargetNode) {
                     MethodCallTargetNode callTarget = (MethodCallTargetNode) usage;
                     verifyInvoke(node, callTarget);
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Mon Feb 17 13:48:41 2014 +0100
@@ -242,7 +242,7 @@
     }
 
     /**
-     * Unsafe access to a int value within an object. The condition parameter gives a hint to the
+     * Unsafe access to an int value within an object. The condition parameter gives a hint to the
      * compiler under which circumstances this access can be moved to an earlier location in the
      * program. The location identity gives a hint to the compiler for improved global value
      * numbering.
@@ -314,8 +314,8 @@
     }
 
     /**
-     * Unsafe access to a Object value within an object. The condition parameter gives a hint to the
-     * compiler under which circumstances this access can be moved to an earlier location in the
+     * Unsafe access to an Object value within an object. The condition parameter gives a hint to
+     * the compiler under which circumstances this access can be moved to an earlier location in the
      * program. The location identity gives a hint to the compiler for improved global value
      * numbering.
      * 
@@ -374,7 +374,7 @@
     }
 
     /**
-     * Write a int value within an object. The location identity gives a hint to the compiler for
+     * Write an int value within an object. The location identity gives a hint to the compiler for
      * improved global value numbering.
      * 
      * @param receiver the object that is written to
@@ -430,8 +430,8 @@
     }
 
     /**
-     * Write a Object value within an object. The location identity gives a hint to the compiler for
-     * improved global value numbering.
+     * Write an Object value within an object. The location identity gives a hint to the compiler
+     * for improved global value numbering.
      * 
      * @param receiver the object that is written to
      * @param offset the offset at which to write to the object in bytes
@@ -444,6 +444,150 @@
     }
 
     /**
+     * Unsafe access to a final boolean value within an object. The condition parameter gives a hint
+     * to the compiler under which circumstances this access can be moved to an earlier location in
+     * the program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     * 
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    public static boolean unsafeGetFinalBoolean(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return UNSAFE.getBoolean(receiver, offset);
+    }
+
+    /**
+     * Unsafe access to a final byte value within an object. The condition parameter gives a hint to
+     * the compiler under which circumstances this access can be moved to an earlier location in the
+     * program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     * 
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    public static byte unsafeGetFinalByte(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return UNSAFE.getByte(receiver, offset);
+    }
+
+    /**
+     * Unsafe access to a final short value within an object. The condition parameter gives a hint
+     * to the compiler under which circumstances this access can be moved to an earlier location in
+     * the program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     * 
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    public static short unsafeGetFinalShort(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return UNSAFE.getShort(receiver, offset);
+    }
+
+    /**
+     * Unsafe access to a final int value within an object. The condition parameter gives a hint to
+     * the compiler under which circumstances this access can be moved to an earlier location in the
+     * program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     * 
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    public static int unsafeGetFinalInt(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return UNSAFE.getInt(receiver, offset);
+    }
+
+    /**
+     * Unsafe access to a final long value within an object. The condition parameter gives a hint to
+     * the compiler under which circumstances this access can be moved to an earlier location in the
+     * program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     * 
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    public static long unsafeGetFinalLong(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return UNSAFE.getLong(receiver, offset);
+    }
+
+    /**
+     * Unsafe access to a final float value within an object. The condition parameter gives a hint
+     * to the compiler under which circumstances this access can be moved to an earlier location in
+     * the program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     * 
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    public static float unsafeGetFinalFloat(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return UNSAFE.getFloat(receiver, offset);
+    }
+
+    /**
+     * Unsafe access to a final double value within an object. The condition parameter gives a hint
+     * to the compiler under which circumstances this access can be moved to an earlier location in
+     * the program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     * 
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    public static double unsafeGetFinalDouble(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return UNSAFE.getDouble(receiver, offset);
+    }
+
+    /**
+     * Unsafe access to a final Object value within an object. The condition parameter gives a hint
+     * to the compiler under which circumstances this access can be moved to an earlier location in
+     * the program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     * 
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    public static Object unsafeGetFinalObject(Object receiver, long offset, boolean condition, Object locationIdentity) {
+        return UNSAFE.getObject(receiver, offset);
+    }
+
+    /**
      * Marks methods that are considered slowpath and should therefore not be inlined by default.
      */
     @Retention(RetentionPolicy.RUNTIME)
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/FrameFactory.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +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.  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.oracle.truffle.api.nodes;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-
-/**
- * Factory for virtual frame creation.
- */
-public interface FrameFactory {
-
-    /**
-     * Creates a new virtual frame from the given frame descriptor and arguments.
-     * 
-     * @param descriptor describes the frame to be created
-     * @param caller the packed caller frame or {@code null}
-     * @param args {@link Arguments} object to be stored in the frame
-     * @return a new virtual frame
-     */
-    VirtualFrame create(FrameDescriptor descriptor, PackedFrame caller, Arguments args);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon Feb 17 13:48:41 2014 +0100
@@ -172,7 +172,7 @@
      * @return the new node
      */
     public final <T extends Node> T replace(T newNode, String reason) {
-        CompilerDirectives.transferToInterpreter();
+        CompilerDirectives.transferToInterpreterAndInvalidate();
         if (this.getParent() == null) {
             throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent.");
         }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -211,27 +211,35 @@
         }
 
         public void leave(Node astNode, VirtualFrame frame, boolean result) {
+            leave(astNode, frame, (Object) result);
         }
 
         public void leave(Node astNode, VirtualFrame frame, byte result) {
+            leave(astNode, frame, (Object) result);
         }
 
         public void leave(Node astNode, VirtualFrame frame, short result) {
+            leave(astNode, frame, (Object) result);
         }
 
         public void leave(Node astNode, VirtualFrame frame, int result) {
+            leave(astNode, frame, (Object) result);
         }
 
         public void leave(Node astNode, VirtualFrame frame, long result) {
+            leave(astNode, frame, (Object) result);
         }
 
         public void leave(Node astNode, VirtualFrame frame, char result) {
+            leave(astNode, frame, (Object) result);
         }
 
         public void leave(Node astNode, VirtualFrame frame, float result) {
+            leave(astNode, frame, (Object) result);
         }
 
         public void leave(Node astNode, VirtualFrame frame, double result) {
+            leave(astNode, frame, (Object) result);
         }
 
         public void leave(Node astNode, VirtualFrame frame, Object result) {
--- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethodNodeManager.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethodNodeManager.java	Mon Feb 17 13:48:41 2014 +0100
@@ -17,6 +17,7 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.ruby.nodes.*;
 import com.oracle.truffle.ruby.nodes.control.*;
+import com.oracle.truffle.ruby.nodes.debug.*;
 import com.oracle.truffle.ruby.nodes.methods.arguments.*;
 import com.oracle.truffle.ruby.nodes.objects.*;
 import com.oracle.truffle.ruby.runtime.*;
@@ -30,7 +31,13 @@
      * given the Object class object, which should already be initialized with all the core classes.
      */
     public static void addMethods(RubyClass rubyObjectClass) {
-        for (MethodDetails methodDetails : getMethods()) {
+        addMethods(rubyObjectClass, getMethods());
+    }
+
+    public static void addMethods(RubyClass rubyObjectClass, List<MethodDetails> methods) {
+        // Same as above, but allows passing of a specific list of core methods.
+        // This allows extending Truffle-Ruby with non-standard Core Method.
+        for (MethodDetails methodDetails : methods) {
             addMethod(rubyObjectClass, methodDetails);
         }
     }
@@ -74,13 +81,14 @@
         getMethods(methods, ThreadNodesFactory.getFactories());
         getMethods(methods, TimeNodesFactory.getFactories());
         getMethods(methods, TrueClassNodesFactory.getFactories());
+        getMethods(methods, DebugNodesFactory.getFactories());
         return methods;
     }
 
     /**
      * Collect up the core methods created by a factory.
      */
-    private static void getMethods(List<MethodDetails> methods, List<? extends NodeFactory<? extends CoreMethodNode>> nodeFactories) {
+    public static void getMethods(List<MethodDetails> methods, List<? extends NodeFactory<? extends CoreMethodNode>> nodeFactories) {
         for (NodeFactory<? extends RubyNode> nodeFactory : nodeFactories) {
             final GeneratedBy generatedBy = nodeFactory.getClass().getAnnotation(GeneratedBy.class);
             final Class<?> nodeClass = generatedBy.value();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/ActiveEnterDebugProbe.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.nodes.debug;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.ruby.nodes.*;
+import com.oracle.truffle.ruby.runtime.*;
+import com.oracle.truffle.ruby.runtime.core.*;
+
+public abstract class ActiveEnterDebugProbe extends RubyProbe {
+
+    private final Assumption activeAssumption;
+
+    private final InlinableMethodImplementation inlinable;
+    private final RubyRootNode inlinedRoot;
+
+    public ActiveEnterDebugProbe(RubyContext context, Assumption activeAssumption, RubyProc proc) {
+        super(context, false);
+        this.activeAssumption = activeAssumption;
+        inlinable = ((InlinableMethodImplementation) proc.getMethod().getImplementation());
+        inlinedRoot = inlinable.getCloneOfPristineRootNode();
+    }
+
+    @Override
+    public void enter(Node astNode, VirtualFrame frame) {
+        try {
+            activeAssumption.check();
+        } catch (InvalidAssumptionException e) {
+            replace(createInactive());
+            return;
+        }
+
+        final RubyArguments arguments = new RubyArguments(inlinable.getDeclarationFrame(), NilPlaceholder.INSTANCE, null, 14);
+        final VirtualFrame inlinedFrame = Truffle.getRuntime().createVirtualFrame(frame.pack(), arguments, inlinable.getFrameDescriptor());
+        inlinedRoot.execute(inlinedFrame);
+    }
+
+    protected abstract InactiveEnterDebugProbe createInactive();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/ActiveLeaveDebugProbe.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.nodes.debug;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.ruby.nodes.*;
+import com.oracle.truffle.ruby.runtime.*;
+import com.oracle.truffle.ruby.runtime.core.*;
+
+public abstract class ActiveLeaveDebugProbe extends RubyProbe {
+
+    private final Assumption activeAssumption;
+
+    private final InlinableMethodImplementation inlinable;
+    private final RubyRootNode inlinedRoot;
+
+    public ActiveLeaveDebugProbe(RubyContext context, Assumption activeAssumption, RubyProc proc) {
+        super(context, false);
+        this.activeAssumption = activeAssumption;
+        inlinable = ((InlinableMethodImplementation) proc.getMethod().getImplementation());
+        inlinedRoot = inlinable.getCloneOfPristineRootNode();
+    }
+
+    @Override
+    public void leave(Node astNode, VirtualFrame frame, Object result) {
+        try {
+            activeAssumption.check();
+        } catch (InvalidAssumptionException e) {
+            replace(createInactive());
+            return;
+        }
+
+        final RubyArguments arguments = new RubyArguments(inlinable.getDeclarationFrame(), NilPlaceholder.INSTANCE, null, result);
+        final VirtualFrame inlinedFrame = Truffle.getRuntime().createVirtualFrame(frame.pack(), arguments, inlinable.getFrameDescriptor());
+        inlinedRoot.execute(inlinedFrame);
+    }
+
+    protected abstract InactiveLeaveDebugProbe createInactive();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/ActiveLineDebugProbe.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.nodes.debug;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.ruby.runtime.*;
+import com.oracle.truffle.ruby.runtime.core.*;
+import com.oracle.truffle.ruby.runtime.debug.*;
+
+public class ActiveLineDebugProbe extends ActiveEnterDebugProbe {
+
+    private final SourceLineLocation sourceLine;
+
+    public ActiveLineDebugProbe(RubyContext context, SourceLineLocation sourceLine, Assumption activeAssumption, RubyProc proc) {
+        super(context, activeAssumption, proc);
+        this.sourceLine = sourceLine;
+    }
+
+    @Override
+    protected InactiveEnterDebugProbe createInactive() {
+        final RubyContext rubyContext = (RubyContext) getContext();
+        final RubyDebugManager manager = rubyContext.getRubyDebugManager();
+        return new InactiveLineDebugProbe(rubyContext, sourceLine, manager.getAssumption(sourceLine));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/ActiveLocalDebugProbe.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.nodes.debug;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.ruby.runtime.*;
+import com.oracle.truffle.ruby.runtime.core.*;
+import com.oracle.truffle.ruby.runtime.debug.*;
+
+public class ActiveLocalDebugProbe extends ActiveLeaveDebugProbe {
+
+    private final MethodLocal methodLocal;
+
+    public ActiveLocalDebugProbe(RubyContext context, MethodLocal methodLocal, Assumption activeAssumption, RubyProc proc) {
+        super(context, activeAssumption, proc);
+        this.methodLocal = methodLocal;
+    }
+
+    @Override
+    protected InactiveLeaveDebugProbe createInactive() {
+        final RubyContext rubyContext = (RubyContext) getContext();
+        final RubyDebugManager manager = rubyContext.getRubyDebugManager();
+        return new InactiveLocalDebugProbe(rubyContext, methodLocal, manager.getAssumption(methodLocal));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/DebugNodes.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.nodes.debug;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.ruby.nodes.core.*;
+import com.oracle.truffle.ruby.runtime.*;
+import com.oracle.truffle.ruby.runtime.control.*;
+import com.oracle.truffle.ruby.runtime.core.*;
+import com.oracle.truffle.ruby.runtime.debug.*;
+import com.oracle.truffle.ruby.runtime.methods.*;
+
+@CoreClass(name = "Debug")
+public abstract class DebugNodes {
+
+    @CoreMethod(names = "break", isModuleMethod = true, needsSelf = false, needsBlock = true, appendCallNode = true, minArgs = 0, maxArgs = 3)
+    public abstract static class BreakNode extends CoreMethodNode {
+
+        public BreakNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public BreakNode(BreakNode prev) {
+            super(prev);
+        }
+
+        @Specialization(order = 1)
+        public NilPlaceholder debugBreak(VirtualFrame frame, Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder undefined0, @SuppressWarnings("unused") UndefinedPlaceholder undefined1,
+                        @SuppressWarnings("unused") UndefinedPlaceholder block) {
+            getContext().runShell(callNode, frame.materialize());
+            return NilPlaceholder.INSTANCE;
+        }
+
+        @Specialization(order = 2)
+        public NilPlaceholder debugBreak(RubyString fileName, int line, @SuppressWarnings("unused") Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder block) {
+            final RubyContext context = getContext();
+            if (context.getConfiguration().getDebug()) {
+                final Source source = context.getSourceManager().get(fileName.toString());
+                final SourceLineLocation lineLocation = new SourceLineLocation(source, line);
+                context.getRubyDebugManager().setBreakpoint(lineLocation, null);
+            }
+            return NilPlaceholder.INSTANCE;
+        }
+
+        @Specialization(order = 3)
+        public NilPlaceholder debugBreak(RubyString fileName, int line, @SuppressWarnings("unused") Node callNode, RubyProc block) {
+            final RubyContext context = getContext();
+            if (context.getConfiguration().getDebug()) {
+                final Source source = context.getSourceManager().get(fileName.toString());
+                final SourceLineLocation lineLocation = new SourceLineLocation(source, line);
+                context.getRubyDebugManager().setBreakpoint(lineLocation, block);
+            }
+            return NilPlaceholder.INSTANCE;
+        }
+
+        @Specialization(order = 4)
+        public NilPlaceholder debugBreak(RubySymbol methodName, RubySymbol localName, @SuppressWarnings("unused") Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder block) {
+            final RubyContext context = getContext();
+            if (context.getConfiguration().getDebug()) {
+                final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString());
+                final MethodLocal methodLocal = new MethodLocal(method.getUniqueIdentifier(), localName.toString());
+                context.getRubyDebugManager().setBreakpoint(methodLocal, null);
+            }
+            return NilPlaceholder.INSTANCE;
+        }
+
+        @Specialization(order = 5)
+        public NilPlaceholder debugBreak(RubySymbol methodName, RubySymbol localName, @SuppressWarnings("unused") Node callNode, RubyProc block) {
+            final RubyContext context = getContext();
+            if (context.getConfiguration().getDebug()) {
+                final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString());
+                final MethodLocal methodLocal = new MethodLocal(method.getUniqueIdentifier(), localName.toString());
+                context.getRubyDebugManager().setBreakpoint(methodLocal, block);
+            }
+            return NilPlaceholder.INSTANCE;
+        }
+
+    }
+
+    @CoreMethod(names = "continue", isModuleMethod = true, needsSelf = false, maxArgs = 0)
+    public abstract static class ContinueNode extends CoreMethodNode {
+
+        public ContinueNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public ContinueNode(ContinueNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public Object debugContinue() {
+            if (getContext().getConfiguration().getDebug()) {
+                throw new BreakShellException();
+            }
+            return NilPlaceholder.INSTANCE;
+        }
+
+    }
+
+    @CoreMethod(names = "enabled?", isModuleMethod = true, needsSelf = false, maxArgs = 0)
+    public abstract static class EnabledNode extends CoreMethodNode {
+
+        public EnabledNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public EnabledNode(ContinueNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public boolean enabled() {
+            return getContext().getConfiguration().getDebug();
+        }
+
+    }
+
+    @CoreMethod(names = "where", isModuleMethod = true, needsSelf = false, appendCallNode = true, minArgs = 1, maxArgs = 1)
+    public abstract static class WhereNode extends CoreMethodNode {
+
+        public WhereNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public WhereNode(WhereNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public NilPlaceholder where(Node callNode) {
+            getContext().getConfiguration().getStandardOut().println(callNode.getSourceSection());
+            return NilPlaceholder.INSTANCE;
+        }
+
+    }
+
+    @CoreMethod(names = "remove", isModuleMethod = true, needsSelf = false, needsBlock = true, minArgs = 2, maxArgs = 2)
+    public abstract static class RemoveNode extends CoreMethodNode {
+
+        public RemoveNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public RemoveNode(RemoveNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public NilPlaceholder debugRemove(RubyString fileName, int line) {
+            final RubyContext context = getContext();
+            if (context.getConfiguration().getDebug()) {
+                final Source source = context.getSourceManager().get(fileName.toString());
+                final SourceLineLocation lineLocation = new SourceLineLocation(source, line);
+                context.getRubyDebugManager().removeBreakpoint(lineLocation);
+            }
+            return NilPlaceholder.INSTANCE;
+        }
+
+        @Specialization
+        public NilPlaceholder debugRemove(RubySymbol methodName, RubySymbol localName) {
+            final RubyContext context = getContext();
+            if (context.getConfiguration().getDebug()) {
+                final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString());
+                final MethodLocal methodLocal = new MethodLocal(method.getUniqueIdentifier(), localName.toString());
+                context.getRubyDebugManager().removeBreakpoint(methodLocal);
+            }
+            return NilPlaceholder.INSTANCE;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/InactiveEnterDebugProbe.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.nodes.debug;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.ruby.runtime.*;
+
+public abstract class InactiveEnterDebugProbe extends RubyProbe {
+
+    private final Assumption inactiveAssumption;
+
+    public InactiveEnterDebugProbe(RubyContext context, Assumption inactiveAssumption) {
+        super(context, false);
+        this.inactiveAssumption = inactiveAssumption;
+    }
+
+    @Override
+    public void enter(Node astNode, VirtualFrame frame) {
+        try {
+            inactiveAssumption.check();
+        } catch (InvalidAssumptionException e) {
+            final ActiveEnterDebugProbe activeNode = createActive();
+            replace(activeNode);
+            activeNode.enter(astNode, frame);
+        }
+    }
+
+    protected abstract ActiveEnterDebugProbe createActive();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/InactiveLeaveDebugProbe.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.nodes.debug;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.ruby.runtime.*;
+
+public abstract class InactiveLeaveDebugProbe extends RubyProbe {
+
+    private final Assumption inactiveAssumption;
+
+    public InactiveLeaveDebugProbe(RubyContext context, Assumption inactiveAssumption) {
+        super(context, false);
+        this.inactiveAssumption = inactiveAssumption;
+    }
+
+    @Override
+    public void leave(Node astNode, VirtualFrame frame, Object result) {
+        try {
+            inactiveAssumption.check();
+        } catch (InvalidAssumptionException e) {
+            final ActiveLeaveDebugProbe activeNode = createActive();
+            replace(activeNode);
+            activeNode.leave(astNode, frame, result);
+        }
+    }
+
+    protected abstract ActiveLeaveDebugProbe createActive();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/InactiveLineDebugProbe.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.nodes.debug;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.ruby.runtime.*;
+import com.oracle.truffle.ruby.runtime.debug.*;
+
+public class InactiveLineDebugProbe extends InactiveEnterDebugProbe {
+
+    private final SourceLineLocation sourceLine;
+
+    public InactiveLineDebugProbe(RubyContext context, SourceLineLocation sourceLine, Assumption inactiveAssumption) {
+        super(context, inactiveAssumption);
+        this.sourceLine = sourceLine;
+    }
+
+    @Override
+    protected ActiveEnterDebugProbe createActive() {
+        final RubyContext rubyContext = (RubyContext) getContext();
+        final RubyDebugManager manager = rubyContext.getRubyDebugManager();
+        return new ActiveLineDebugProbe(rubyContext, sourceLine, manager.getAssumption(sourceLine), manager.getBreakpoint(sourceLine));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/InactiveLocalDebugProbe.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.nodes.debug;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.ruby.runtime.*;
+import com.oracle.truffle.ruby.runtime.debug.*;
+
+public class InactiveLocalDebugProbe extends InactiveLeaveDebugProbe {
+
+    private final MethodLocal methodLocal;
+
+    public InactiveLocalDebugProbe(RubyContext context, MethodLocal methodLocal, Assumption inactiveAssumption) {
+        super(context, inactiveAssumption);
+        this.methodLocal = methodLocal;
+    }
+
+    @Override
+    protected ActiveLeaveDebugProbe createActive() {
+        final RubyContext rubyContext = (RubyContext) getContext();
+        final RubyDebugManager manager = rubyContext.getRubyDebugManager();
+        return new ActiveLocalDebugProbe(rubyContext, methodLocal, manager.getAssumption(methodLocal), manager.getBreakpoint(methodLocal));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/RubyProbe.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.nodes.debug;
+
+import com.oracle.truffle.api.nodes.instrument.*;
+import com.oracle.truffle.ruby.runtime.*;
+
+/**
+ * A "probe node" implemented specifically for the Ruby implementation; subclasses need only
+ * override those members of {@link InstrumentationProbeEvents} for which some action is needed.
+ */
+public abstract class RubyProbe extends InstrumentationProbeNode.DefaultProbeNode {
+
+    protected final boolean oneShot;
+
+    protected final RubyContext context;
+
+    /**
+     * OneShot is this a one-shot (self-removing) probe?
+     */
+    public RubyProbe(RubyContext context, boolean oneShot) {
+        super(context);
+        this.oneShot = oneShot;
+        this.context = context;
+    }
+
+    /**
+     * Is this a one-shot (self-removing) probe? If so, it will remove itself the first time
+     * activated.
+     */
+    public boolean isOneShot() {
+        return oneShot;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/RubyTraceProbe.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.nodes.debug;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.ruby.runtime.*;
+import com.oracle.truffle.ruby.runtime.subsystems.*;
+
+/**
+ * A "trace" probe that has no runtime cost until activated, at which time it invokes a trace
+ * message.
+ */
+public final class RubyTraceProbe extends RubyProbe {
+
+    private final Assumption notTracingAssumption;
+
+    @CompilerDirectives.CompilationFinal private boolean tracingEverEnabled = false;
+
+    public RubyTraceProbe(RubyContext context) {
+        super(context, false);
+        this.notTracingAssumption = context.getTraceManager().getNotTracingAssumption();
+    }
+
+    @Override
+    public void enter(Node astNode, VirtualFrame frame) {
+        if (!tracingEverEnabled) {
+            try {
+                notTracingAssumption.check();
+            } catch (InvalidAssumptionException e) {
+                tracingEverEnabled = true;
+            }
+        }
+        final TraceManager traceManager = context.getTraceManager();
+        if (tracingEverEnabled && traceManager.hasTraceProc()) {
+            final SourceSection sourceSection = astNode.getEncapsulatingSourceSection();
+            traceManager.trace("line", sourceSection.getSource().getName(), sourceSection.getStartLine(), 0, null, null);
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/DefaultRubyNodeInstrumenter.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/DefaultRubyNodeInstrumenter.java	Mon Feb 17 13:48:41 2014 +0100
@@ -9,7 +9,9 @@
  */
 package com.oracle.truffle.ruby.parser;
 
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.nodes.instrument.*;
+import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.ruby.nodes.*;
 import com.oracle.truffle.ruby.nodes.debug.*;
 import com.oracle.truffle.ruby.runtime.*;
@@ -26,17 +28,33 @@
     public DefaultRubyNodeInstrumenter() {
     }
 
-    public RubyNode instrumentAsStatement(RubyNode rubyNode) {
-        assert rubyNode != null;
-        assert !(rubyNode instanceof RubyProxyNode);
-        final RubyContext context = rubyNode.getContext();
+    public RubyNode instrumentAsStatement(RubyNode node) {
+        assert node != null;
+
+        final RubyContext context = node.getContext();
+
+        RubyProxyNode proxy;
+
+        if (node instanceof RubyProxyNode) {
+            proxy = (RubyProxyNode) node;
+        } else {
+            proxy = new RubyProxyNode(node.getContext(), node);
+            proxy.markAs(NodePhylum.STATEMENT);
+            proxy.clearSourceSection();
+            proxy.assignSourceSection(node.getSourceSection());
+        }
+
         if (context.getConfiguration().getTrace()) {
-            final RubyProxyNode proxy = new RubyProxyNode(context, rubyNode);
-            proxy.markAs(NodePhylum.STATEMENT);
             proxy.getProbeChain().appendProbe(new RubyTraceProbe(context));
-            return proxy;
         }
-        return rubyNode;
+
+        if (context.getConfiguration().getDebug()) {
+            final SourceSection sourceSection = proxy.getChild().getSourceSection();
+            final SourceLineLocation sourceLine = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine());
+            proxy.getProbeChain().appendProbe(new InactiveLineDebugProbe(context, sourceLine, context.getRubyDebugManager().getAssumption(sourceLine)));
+        }
+
+        return proxy;
     }
 
     public RubyNode instrumentAsCall(RubyNode node, String callName) {
@@ -44,7 +62,27 @@
     }
 
     public RubyNode instrumentAsLocalAssignment(RubyNode node, UniqueMethodIdentifier methodIdentifier, String localName) {
-        return node;
+        assert node != null;
+
+        final RubyContext context = node.getContext();
+
+        RubyProxyNode proxy;
+
+        if (node instanceof RubyProxyNode) {
+            proxy = (RubyProxyNode) node;
+        } else {
+            proxy = new RubyProxyNode(node.getContext(), node);
+            proxy.markAs(NodePhylum.STATEMENT);
+            proxy.clearSourceSection();
+            proxy.assignSourceSection(node.getSourceSection());
+        }
+
+        if (context.getConfiguration().getDebug()) {
+            final MethodLocal methodLocal = new MethodLocal(methodIdentifier, localName);
+            proxy.getProbeChain().appendProbe(new InactiveLocalDebugProbe(context, methodLocal, context.getRubyDebugManager().getAssumption(methodLocal)));
+        }
+
+        return proxy;
     }
 
 }
--- a/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/Translator.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/Translator.java	Mon Feb 17 13:48:41 2014 +0100
@@ -1102,7 +1102,6 @@
 
     @Override
     public Object visitLocalAsgnNode(org.jrubyparser.ast.LocalAsgnNode node) {
-
         final SourceSection sourceSection = translate(node.getPosition());
 
         if (environment.getNeverAssignInParentScope()) {
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyContext.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyContext.java	Mon Feb 17 13:48:41 2014 +0100
@@ -22,6 +22,7 @@
 import com.oracle.truffle.ruby.runtime.configuration.*;
 import com.oracle.truffle.ruby.runtime.control.*;
 import com.oracle.truffle.ruby.runtime.core.*;
+import com.oracle.truffle.ruby.runtime.debug.*;
 import com.oracle.truffle.ruby.runtime.methods.*;
 import com.oracle.truffle.ruby.runtime.objects.*;
 import com.oracle.truffle.ruby.runtime.subsystems.*;
@@ -41,6 +42,7 @@
     private final FiberManager fiberManager;
     private final AtExitManager atExitManager;
     private final DebugManager debugManager;
+    private final RubyDebugManager rubyDebugManager;
     private final SourceManager sourceManager;
     private final ASTPrinter astPrinter;
 
@@ -77,6 +79,7 @@
         sourceManager = new SourceManager();
 
         debugManager = new DefaultDebugManager(this);
+        rubyDebugManager = new RubyDebugManager();
 
         // Must initialize threads before fibers
 
@@ -300,4 +303,8 @@
         return sourceManager;
     }
 
+    public RubyDebugManager getRubyDebugManager() {
+        return rubyDebugManager;
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/MethodLocal.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.runtime.debug;
+
+import com.oracle.truffle.ruby.runtime.methods.*;
+
+/*
+ * Identifies a local in a method.
+ */
+public class MethodLocal {
+
+    private final UniqueMethodIdentifier method;
+    private final String local;
+
+    public MethodLocal(UniqueMethodIdentifier method, String local) {
+        this.method = method;
+        this.local = local;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((local == null) ? 0 : local.hashCode());
+        result = prime * result + ((method == null) ? 0 : method.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        MethodLocal other = (MethodLocal) obj;
+        if (local == null) {
+            if (other.local != null) {
+                return false;
+            }
+        } else if (!local.equals(other.local)) {
+            return false;
+        }
+        if (method == null) {
+            if (other.method != null) {
+                return false;
+            }
+        } else if (!method.equals(other.method)) {
+            return false;
+        }
+        return true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyDebugManager.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.runtime.debug;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.utilities.*;
+import com.oracle.truffle.ruby.runtime.core.*;
+
+public final class RubyDebugManager {
+
+    private final Map<SourceLineLocation, CyclicAssumption> lineAssumptions = new HashMap<>();
+    private final Map<SourceLineLocation, RubyProc> lineBreakpoints = new HashMap<>();
+
+    private final Map<MethodLocal, CyclicAssumption> localAssumptions = new HashMap<>();
+    private final Map<MethodLocal, RubyProc> localBreakpoints = new HashMap<>();
+
+    public void setBreakpoint(SourceLineLocation sourceLine, RubyProc proc) {
+        final CyclicAssumption assumption = lineAssumptions.get(sourceLine);
+
+        if (assumption == null) {
+            throw new RuntimeException("Breakpoint " + sourceLine + " not found");
+        } else {
+            lineBreakpoints.put(sourceLine, proc);
+            assumption.invalidate();
+        }
+    }
+
+    public void setBreakpoint(MethodLocal methodLocal, RubyProc proc) {
+        final CyclicAssumption assumption = localAssumptions.get(methodLocal);
+
+        if (assumption == null) {
+            throw new RuntimeException("Breakpoint " + methodLocal + " not found");
+        } else {
+            localBreakpoints.put(methodLocal, proc);
+            assumption.invalidate();
+        }
+    }
+
+    public void removeBreakpoint(SourceLineLocation sourceLine) {
+        final CyclicAssumption assumption = lineAssumptions.get(sourceLine);
+
+        if (assumption == null) {
+            throw new RuntimeException("Breakpoint " + sourceLine + " not found");
+        } else {
+            lineBreakpoints.remove(sourceLine);
+            assumption.invalidate();
+        }
+    }
+
+    public void removeBreakpoint(MethodLocal methodLocal) {
+        final CyclicAssumption assumption = localAssumptions.get(methodLocal);
+
+        if (assumption == null) {
+            throw new RuntimeException("Breakpoint " + methodLocal + " not found");
+        } else {
+            localBreakpoints.remove(methodLocal);
+            assumption.invalidate();
+        }
+    }
+
+    public Assumption getAssumption(SourceLineLocation sourceLine) {
+        CyclicAssumption assumption = lineAssumptions.get(sourceLine);
+
+        if (assumption == null) {
+            assumption = new CyclicAssumption(sourceLine.toString());
+            lineAssumptions.put(sourceLine, assumption);
+        }
+
+        return assumption.getAssumption();
+    }
+
+    public RubyProc getBreakpoint(SourceLineLocation sourceLine) {
+        return lineBreakpoints.get(sourceLine);
+    }
+
+    public Assumption getAssumption(MethodLocal methodLocal) {
+        CyclicAssumption assumption = localAssumptions.get(methodLocal);
+
+        if (assumption == null) {
+            assumption = new CyclicAssumption(methodLocal.toString());
+            localAssumptions.put(methodLocal, assumption);
+        }
+
+        return assumption.getAssumption();
+    }
+
+    public RubyProc getBreakpoint(MethodLocal methodLocal) {
+        return localBreakpoints.get(methodLocal);
+    }
+
+}
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProbe.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.runtime.debug;
-
-import com.oracle.truffle.api.nodes.instrument.*;
-import com.oracle.truffle.ruby.runtime.*;
-
-/**
- * A "probe node" implemented specifically for the Ruby implementation; subclasses need only
- * override those members of {@link InstrumentationProbeEvents} for which some action is needed.
- */
-public abstract class RubyProbe extends InstrumentationProbeNode.DefaultProbeNode {
-
-    protected final boolean oneShot;
-
-    protected final RubyContext context;
-
-    /**
-     * OneShot is this a one-shot (self-removing) probe?
-     */
-    public RubyProbe(RubyContext context, boolean oneShot) {
-        super(context);
-        this.oneShot = oneShot;
-        this.context = context;
-    }
-
-    /**
-     * Is this a one-shot (self-removing) probe? If so, it will remove itself the first time
-     * activated.
-     */
-    public boolean isOneShot() {
-        return oneShot;
-    }
-}
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyTraceProbe.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.runtime.debug;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.ruby.runtime.*;
-import com.oracle.truffle.ruby.runtime.subsystems.*;
-
-/**
- * A "trace" probe that has no runtime cost until activated, at which time it invokes a trace
- * message.
- */
-public final class RubyTraceProbe extends RubyProbe {
-
-    private final Assumption notTracingAssumption;
-
-    @CompilerDirectives.CompilationFinal private boolean tracingEverEnabled = false;
-
-    public RubyTraceProbe(RubyContext context) {
-        super(context, false);
-        this.notTracingAssumption = context.getTraceManager().getNotTracingAssumption();
-    }
-
-    @Override
-    public void enter(Node astNode, VirtualFrame frame) {
-        if (!tracingEverEnabled) {
-            try {
-                notTracingAssumption.check();
-            } catch (InvalidAssumptionException e) {
-                tracingEverEnabled = true;
-            }
-        }
-        final TraceManager traceManager = context.getTraceManager();
-        if (tracingEverEnabled && traceManager.hasTraceProc()) {
-            final SourceSection sourceSection = astNode.getEncapsulatingSourceSection();
-            traceManager.trace("line", sourceSection.getSource().getName(), sourceSection.getStartLine(), 0, null, null);
-        }
-    }
-}
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLSimpleTestSuite.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLSimpleTestSuite.java	Mon Feb 17 13:48:41 2014 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.sl.test;
 
+import org.junit.*;
 import org.junit.runner.*;
 
 @RunWith(SLTestRunner.class)
@@ -32,4 +33,11 @@
         SLTestRunner.runInMain(SLSimpleTestSuite.class, args);
     }
 
+    /*
+     * Our "mx unittest" command looks for methods that are annotated with @Test. By just defining
+     * an empty method, this class gets included and the test suite is properly executed.
+     */
+    @Test
+    public void unittest() {
+    }
 }
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java	Mon Feb 17 13:48:41 2014 +0100
@@ -89,11 +89,6 @@
         return testCases;
     }
 
-    @Override
-    public void filter(Filter filter) throws NoTestsRemainException {
-        super.filter(filter);
-    }
-
     protected List<TestCase> createTests(final Class<?> c) throws IOException, InitializationError {
         SLTestSuite suite = c.getAnnotation(SLTestSuite.class);
         if (suite == null) {
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError05.output	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.sl.test/tests/error/TypeError05.output	Mon Feb 17 13:48:41 2014 +0100
@@ -1,1 +1,1 @@
-Type error at TypeError05.sl line 3 col 3: operation "call" not defined for Boolean true
+Type error at TypeError05.sl line 3 col 3: operation "invoke" not defined for Boolean true
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Mon Feb 17 13:48:41 2014 +0100
@@ -80,7 +80,7 @@
  * <li>Basic control flow statements: {@link SLBlockNode blocks}, {@link SLIfNode if},
  * {@link SLWhileNode while} with {@link SLBreakNode break} and {@link SLContinueNode continue},
  * {@link SLReturnNode return}.
- * <li>Function calls: {@link SLCallNode calls} are efficiently implemented with
+ * <li>Function calls: {@link SLInvokeNode invocations} are efficiently implemented with
  * {@link SLAbstractDispatchNode polymorphic inline caches}.
  * </ul>
  * 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java	Mon Feb 17 13:48:41 2014 +0100
@@ -38,14 +38,14 @@
 
     @Specialization
     public String defineFunction(String code) {
-        return doDefineFunction(getContext(), code);
+        doDefineFunction(getContext(), code);
+        return code;
     }
 
     @SlowPath
-    private static String doDefineFunction(SLContext context, String code) {
+    private static void doDefineFunction(SLContext context, String code) {
         Source source = context.getSourceManager().get("[defineFunction]", code);
         /* The same parsing code as for parsing the initial source. */
         Parser.parseSL(context, source);
-        return code;
     }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLTypes.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLTypes.java	Mon Feb 17 13:48:41 2014 +0100
@@ -60,11 +60,11 @@
     }
 
     /**
-     * Informs the Truffle DSL that a primitive {@code long} value can used in all specializations
-     * where a {@link BigInteger} is expected. This models the semantic of SL: It only has an
-     * arbitrary precision Number type (implemented as {@link BigInteger}, and {@code long} is only
-     * used as a performance optimization to avoid the costly {@link BigInteger} arithmetic for
-     * values that fit into a 64-bit primitive value.
+     * Informs the Truffle DSL that a primitive {@code long} value can be used in all
+     * specializations where a {@link BigInteger} is expected. This models the semantic of SL: It
+     * only has an arbitrary precision Number type (implemented as {@link BigInteger}, and
+     * {@code long} is only used as a performance optimization to avoid the costly
+     * {@link BigInteger} arithmetic for values that fit into a 64-bit primitive value.
      */
     @ImplicitCast
     public BigInteger castBigInteger(long value) {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLAbstractDispatchNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLAbstractDispatchNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -35,14 +35,14 @@
  * a single {@link SLGenericDispatchNode}. All this rewriting happens on runtime, based on profiling
  * feedback of the actual execution.
  * <p>
- * Example of the chain of nodes ({@code C}: {@link SLCallNode}; {@code U}:
+ * Example of the chain of nodes ({@code I}: {@link SLInvokeNode}; {@code U}:
  * {@link SLUninitializedDispatchNode}; {@code D}: {@link SLDirectDispatchNode}; {@code G}:
  * {@link SLGenericDispatchNode}):
  * <ol>
- * <li>After parsing: {@code C->U}
- * <li>After execution of function {@code f1}: {@code C->D(f1)->U}
- * <li>After execution of function {@code f2}: {@code C->D(f1)->D(f2)->U}
- * <li>After execution of function {@code f3}: {@code C->G}
+ * <li>After parsing: {@code I->U}
+ * <li>After execution of function {@code f1}: {@code I->D(f1)->U}
+ * <li>After execution of function {@code f2}: {@code I->D(f1)->D(f2)->U}
+ * <li>After execution of function {@code f3}: {@code I->G}
  * </ol>
  * */
 public abstract class SLAbstractDispatchNode extends Node {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLCallNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, 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.truffle.sl.nodes.call;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * The node for a function call in SL. Since SL has first class functions, the {@link SLFunction
- * target function} can be computed by an {@link #functionNode arbitrary expression}. This node is
- * responsible for evaluating this expression, as well as evaluating the {@link #argumentNodes
- * arguments}. The actual call dispatch is then delegated to a chain of
- * {@link SLAbstractDispatchNode}s that form a polymorphic inline cache.
- */
-@NodeInfo(shortName = "call")
-public final class SLCallNode extends SLExpressionNode {
-
-    public static SLCallNode create(SLExpressionNode function, SLExpressionNode[] arguments) {
-        return new SLCallNode(function, arguments, new SLUninitializedDispatchNode());
-    }
-
-    @Child protected SLExpressionNode functionNode;
-    @Children protected final SLExpressionNode[] argumentNodes;
-    @Child protected SLAbstractDispatchNode dispatchNode;
-
-    private SLCallNode(SLExpressionNode functionNode, SLExpressionNode[] argumentNodes, SLAbstractDispatchNode dispatchNode) {
-        this.functionNode = adoptChild(functionNode);
-        this.argumentNodes = adoptChildren(argumentNodes);
-        this.dispatchNode = adoptChild(dispatchNode);
-    }
-
-    @Override
-    @ExplodeLoop
-    public Object executeGeneric(VirtualFrame frame) {
-        SLFunction function = evaluateFunction(frame);
-
-        /*
-         * The number of arguments is constant for one call node. During compilation, the loop is
-         * unrolled and the execute methods of all arguments are inlined. This is triggered by the
-         * ExplodeLoop annotation on the method. The compiler assertion below illustrates that the
-         * array length is really constant.
-         */
-        CompilerAsserts.compilationConstant(argumentNodes.length);
-
-        Object[] argumentValues = new Object[argumentNodes.length];
-        for (int i = 0; i < argumentNodes.length; i++) {
-            argumentValues[i] = argumentNodes[i].executeGeneric(frame);
-        }
-        SLArguments arguments = new SLArguments(argumentValues);
-
-        return dispatchNode.executeDispatch(frame, function, arguments);
-    }
-
-    private SLFunction evaluateFunction(VirtualFrame frame) {
-        try {
-            /*
-             * The function node must evaluate to a SLFunction value, so we call
-             * function-specialized method.
-             */
-            return functionNode.executeFunction(frame);
-        } catch (UnexpectedResultException ex) {
-            /*
-             * The function node evaluated to a non-function result. This is a type error in the SL
-             * program. We report it with the same exception that Truffle DSL generated nodes use to
-             * report type errors.
-             */
-            throw new UnsupportedSpecializationException(this, new Node[]{functionNode}, ex.getResult());
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLInvokeNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2013, 2014, 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.truffle.sl.nodes.call;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * The node for function invocation in SL. Since SL has first class functions, the
+ * {@link SLFunction target function} can be computed by an {@link #functionNode arbitrary
+ * expression}. This node is responsible for evaluating this expression, as well as evaluating the
+ * {@link #argumentNodes arguments}. The actual dispatch is then delegated to a chain of
+ * {@link SLAbstractDispatchNode}s that form a polymorphic inline cache.
+ */
+@NodeInfo(shortName = "invoke")
+public final class SLInvokeNode extends SLExpressionNode {
+
+    public static SLInvokeNode create(SLExpressionNode function, SLExpressionNode[] arguments) {
+        return new SLInvokeNode(function, arguments, new SLUninitializedDispatchNode());
+    }
+
+    @Child protected SLExpressionNode functionNode;
+    @Children protected final SLExpressionNode[] argumentNodes;
+    @Child protected SLAbstractDispatchNode dispatchNode;
+
+    private SLInvokeNode(SLExpressionNode functionNode, SLExpressionNode[] argumentNodes, SLAbstractDispatchNode dispatchNode) {
+        this.functionNode = adoptChild(functionNode);
+        this.argumentNodes = adoptChildren(argumentNodes);
+        this.dispatchNode = adoptChild(dispatchNode);
+    }
+
+    @Override
+    @ExplodeLoop
+    public Object executeGeneric(VirtualFrame frame) {
+        SLFunction function = evaluateFunction(frame);
+
+        /*
+         * The number of arguments is constant for one invoke node. During compilation, the loop is
+         * unrolled and the execute methods of all arguments are inlined. This is triggered by the
+         * ExplodeLoop annotation on the method. The compiler assertion below illustrates that the
+         * array length is really constant.
+         */
+        CompilerAsserts.compilationConstant(argumentNodes.length);
+
+        Object[] argumentValues = new Object[argumentNodes.length];
+        for (int i = 0; i < argumentNodes.length; i++) {
+            argumentValues[i] = argumentNodes[i].executeGeneric(frame);
+        }
+        SLArguments arguments = new SLArguments(argumentValues);
+
+        return dispatchNode.executeDispatch(frame, function, arguments);
+    }
+
+    private SLFunction evaluateFunction(VirtualFrame frame) {
+        try {
+            /*
+             * The function node must evaluate to a SLFunction value, so we call
+             * function-specialized method.
+             */
+            return functionNode.executeFunction(frame);
+        } catch (UnexpectedResultException ex) {
+            /*
+             * The function node evaluated to a non-function result. This is a type error in the SL
+             * program. We report it with the same exception that Truffle DSL generated nodes use to
+             * report type errors.
+             */
+            throw new UnsupportedSpecializationException(this, new Node[]{functionNode}, ex.getResult());
+        }
+    }
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLUninitializedDispatchNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLUninitializedDispatchNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -54,9 +54,9 @@
             cur = cur.getParent();
             depth++;
         }
-        SLCallNode callNode = (SLCallNode) cur.getParent();
+        SLInvokeNode invokeNode = (SLInvokeNode) cur.getParent();
 
-        SLAbstractDispatchNode specialized;
+        SLAbstractDispatchNode replacement;
         if (function.getCallTarget() == null) {
             /* Corner case: the function is not defined, so report an error to the user. */
             throw new SLException("Call of undefined function: " + function.getName());
@@ -64,21 +64,21 @@
         } else if (depth < INLINE_CACHE_SIZE) {
             /* Extend the inline cache. Allocate the new cache entry, and the new end of the cache. */
             SLAbstractDispatchNode next = new SLUninitializedDispatchNode();
-            SLAbstractDispatchNode direct = new SLDirectDispatchNode(next, function);
+            replacement = new SLDirectDispatchNode(next, function);
             /* Replace ourself with the new cache entry. */
-            specialized = replace(direct);
+            replace(replacement);
 
         } else {
             /* Cache size exceeded, fall back to a single generic dispatch node. */
-            SLAbstractDispatchNode generic = new SLGenericDispatchNode();
+            replacement = new SLGenericDispatchNode();
             /* Replace the whole chain, not just ourself, with the new generic node. */
-            specialized = callNode.dispatchNode.replace(generic);
+            invokeNode.dispatchNode.replace(replacement);
         }
 
         /*
          * Execute the newly created node perform the actual dispatch. That saves us from
          * duplicating the actual call logic here.
          */
-        return specialized.executeDispatch(frame, function, arguments);
+        return replacement.executeDispatch(frame, function, arguments);
     }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -70,7 +70,9 @@
      * operand are {@link BigInteger} values. Because the type system defines an
      * {@link ImplicitCast implicit conversion} from {@code long} to {@link BigInteger} in
      * {@link SLTypes#castBigInteger(long)}, this specialization is also taken if the left or the
-     * right operand is a {@code long} value.
+     * right operand is a {@code long} value. Because the {@link #add(long, long) long}
+     * specialization} has the {@code rewriteOn} attribute, this specialization is also taken if
+     * both input values are {@code long} values but the primitive addition overflows.
      */
     @Specialization
     protected BigInteger add(BigInteger left, BigInteger right) {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -42,17 +42,17 @@
      */
     protected abstract FrameSlot getSlot();
 
-    @Specialization(rewriteOn = {FrameSlotTypeException.class})
+    @Specialization(rewriteOn = FrameSlotTypeException.class)
     protected long readLong(VirtualFrame frame) throws FrameSlotTypeException {
         return frame.getLong(getSlot());
     }
 
-    @Specialization(rewriteOn = {FrameSlotTypeException.class})
+    @Specialization(rewriteOn = FrameSlotTypeException.class)
     protected boolean readBoolean(VirtualFrame frame) throws FrameSlotTypeException {
         return frame.getBoolean(getSlot());
     }
 
-    @Specialization(order = 1, rewriteOn = {FrameSlotTypeException.class})
+    @Specialization(order = 1, rewriteOn = FrameSlotTypeException.class)
     protected Object readObject(VirtualFrame frame) throws FrameSlotTypeException {
         return frame.getObject(getSlot());
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java	Mon Feb 17 13:48:41 2014 +0100
@@ -31,7 +31,7 @@
  * Node to write a local variable to a function's {@link VirtualFrame frame}. The Truffle frame API
  * allows to store primitive values of all Java primitive types, and Object values.
  */
-@NodeChild(value = "valueNode")
+@NodeChild("valueNode")
 @NodeField(name = "slot", type = FrameSlot.class)
 public abstract class SLWriteLocalVariableNode extends SLExpressionNode {
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Mon Feb 17 13:48:41 2014 +0100
@@ -197,7 +197,7 @@
 
     public SLExpressionNode createCall(Token nameToken, List<SLExpressionNode> parameterNodes) {
         SLExpressionNode functionNode = createRead(nameToken);
-        return assignSource(nameToken, SLCallNode.create(functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()])));
+        return assignSource(nameToken, SLInvokeNode.create(functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()])));
     }
 
     public SLExpressionNode createAssignment(Token nameToken, SLExpressionNode valueNode) {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLArguments.java	Thu Feb 06 17:41:51 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLArguments.java	Mon Feb 17 13:48:41 2014 +0100
@@ -36,7 +36,7 @@
     private final Object[] argumentValues;
 
     /**
-     * Used by the caller, i.e., the {@link SLCallNode node that performs a function call}.
+     * Used by the caller, i.e., the {@link SLInvokeNode node that performs a function call}.
      */
     public SLArguments(Object[] arguments) {
         this.argumentValues = arguments;
--- a/mx/mx_graal.py	Thu Feb 06 17:41:51 2014 +0100
+++ b/mx/mx_graal.py	Mon Feb 17 13:48:41 2014 +0100
@@ -81,6 +81,8 @@
 
 _minVersion = mx.VersionSpec('1.7.0_04')
 
+JDK_UNIX_PERMISSIONS = 0755
+
 def _get_vm():
     """
     Gets the configured VM, presenting a dialogue if there is no currently configured VM.
@@ -324,7 +326,7 @@
 
             assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg
             if mx.get_os() != 'windows':
-                chmodRecursive(jdk, 0755)
+                chmodRecursive(jdk, JDK_UNIX_PERMISSIONS)
             shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'original'))
 
 
@@ -402,7 +404,9 @@
                 fd, tmp = tempfile.mkstemp(suffix='', prefix='graal.jar', dir=jreLibDir)
                 shutil.copyfile(graalJar, tmp)
                 os.close(fd)
-                shutil.move(tmp, join(jreLibDir, 'graal.jar'))
+                graalJar = join(jreLibDir, 'graal.jar')
+                shutil.move(tmp, graalJar)
+                os.chmod(graalJar, JDK_UNIX_PERMISSIONS)
 
 # run a command in the windows SDK Debug Shell
 def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None):
@@ -568,7 +572,7 @@
         vmDir = join(_vmLibDirInJdk(jdk), vm)
         if not exists(vmDir):
             if mx.get_os() != 'windows':
-                chmodRecursive(jdk, 0755)
+                chmodRecursive(jdk, JDK_UNIX_PERMISSIONS)
             mx.log('Creating VM directory in JDK7: ' + vmDir)
             os.makedirs(vmDir)
 
@@ -685,7 +689,7 @@
         if not found:
             mx.log('Appending "' + prefix + 'KNOWN" to ' + jvmCfg)
             if mx.get_os() != 'windows':
-                os.chmod(jvmCfg, 0755)
+                os.chmod(jvmCfg, JDK_UNIX_PERMISSIONS)
             with open(jvmCfg, 'w') as f:
                 for line in lines:
                     if line.startswith(prefix):
@@ -708,7 +712,7 @@
     """run the fastdebug build of VM selected by the '--vm' option"""
     return vm(args, vmbuild='fastdebug')
 
-def vm(args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, vmbuild=None):
+def _parseVmArgs(args, vm=None, cwd=None, vmbuild=None):
     """run the VM selected by the '--vm' option"""
 
     if vm is None:
@@ -725,10 +729,6 @@
     mx.expand_project_in_args(args)
     if _make_eclipse_launch:
         mx.make_eclipse_launch(args, 'graal-' + build, name=None, deps=mx.project('com.oracle.graal.hotspot').all_deps([], True))
-    if len([a for a in args if 'PrintAssembly' in a]) != 0:
-        hsdis([], copyToDir=_vmLibDirInJdk(jdk))
-    if mx.java().debug_port is not None:
-        args = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(mx.java().debug_port)] + args
     if _jacoco == 'on' or _jacoco == 'append':
         jacocoagent = mx.library("JACOCOAGENT", True)
         # Exclude all compiler tests and snippets
@@ -746,9 +746,6 @@
                         'destfile' : 'jacoco.exec'
         }
         args = ['-javaagent:' + jacocoagent.get_path(True) + '=' + ','.join([k + '=' + v for k, v in agentOptions.items()])] + args
-    if '-d64' not in args:
-        args = ['-d64'] + args
-
     exe = join(jdk, 'bin', mx.exe_suffix('java'))
     pfx = _vm_prefix.split() if _vm_prefix is not None else []
 
@@ -757,7 +754,12 @@
         if  len(ignoredArgs) > 0:
             mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs))
 
-    return mx.run(pfx + [exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout)
+    args = mx.java().processArgs(args)
+    return (pfx, exe, vm, args, cwd)
+
+def vm(args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, vmbuild=None):
+    (pfx_, exe_, vm_, args_, cwd) = _parseVmArgs(args, vm, cwd, vmbuild)
+    return mx.run(pfx_ + [exe_, '-' + vm_] + args_, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout)
 
 def _find_classes_with_annotations(p, pkgRoot, annotations, includeInnerClasses=False):
     """
@@ -1067,21 +1069,23 @@
         mx.pylint([])
         tasks.append(t.stop())
 
-        t = Task('Clean')
-        cleanArgs = []
-        if not args.cleanNative:
-            cleanArgs.append('--no-native')
-        if not args.cleanJava:
-            cleanArgs.append('--no-java')
-        clean(cleanArgs)
-        tasks.append(t.stop())
+        def _clean(name='Clean'):
+            t = Task(name)
+            cleanArgs = []
+            if not args.cleanNative:
+                cleanArgs.append('--no-native')
+            if not args.cleanJava:
+                cleanArgs.append('--no-java')
+            clean(cleanArgs)
+            tasks.append(t.stop())
+        _clean()
 
         t = Task('IDEConfigCheck')
         mx.ideclean([])
         mx.ideinit([])
         tasks.append(t.stop())
 
-        eclipse_exe = os.environ.get('ECLIPSE_EXE')
+        eclipse_exe = mx.get_env('ECLIPSE_EXE')
         if eclipse_exe is not None:
             t = Task('CodeFormatCheck')
             if mx.eclipseformat(['-e', eclipse_exe]) != 0:
@@ -1094,8 +1098,15 @@
             t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.')
         tasks.append(t.stop())
 
-        t = Task('BuildJava')
-        build(['--no-native', '--jdt-warning-as-error'])
+        if mx.get_env('JDT'):
+            t = Task('BuildJavaWithEcj')
+            build(['--no-native', '--jdt-warning-as-error'])
+            tasks.append(t.stop())
+
+            _clean('CleanAfterEcjBuild')
+
+        t = Task('BuildJavaWithJavac')
+        build(['--no-native', '--force-javac'])
         tasks.append(t.stop())
 
         t = Task('Checkstyle')
@@ -1251,6 +1262,76 @@
         with open(resultFile, 'w') as f:
             f.write(json.dumps(results))
 
+def jmh(args):
+    """run the JMH_BENCHMARKS"""
+
+    # TODO: add option for `mvn clean package'
+    # TODO: add options to pass through arguments directly to JMH
+
+    vmArgs, benchmarks = _extract_VM_args(args)
+    jmhPath = mx.get_env('JMH_BENCHMARKS', None)
+    if not jmhPath or not exists(jmhPath):
+        mx.abort("$JMH_BENCHMARKS not properly definied")
+
+    def _blackhole(x):
+        mx.logv(x[:-1])
+    mx.log("Building benchmarks...")
+    mx.run(['mvn', 'package'], cwd = jmhPath, out = _blackhole)
+
+    matchedSuites = set()
+    numBench = [0]
+    for micros in os.listdir(jmhPath):
+        absoluteMicro = os.path.join(jmhPath, micros)
+        if not os.path.isdir(absoluteMicro):
+            continue
+        if not micros.startswith("micros-"):
+            mx.logv('JMH: ignored ' + absoluteMicro + " because it doesn't start with 'micros-'")
+            continue
+
+        microJar = os.path.join(absoluteMicro, "target", "microbenchmarks.jar")
+        if not exists(microJar):
+            mx.logv('JMH: ignored ' + absoluteMicro + " because it doesn't contain the expected jar file ('" + microJar + "')")
+            continue
+        if benchmarks:
+            def _addBenchmark(x):
+                if x.startswith("Benchmark:"):
+                    return
+                match = False
+                for b in benchmarks:
+                    match = match or (b in x)
+
+                if match:
+                    numBench[0] += 1
+                    matchedSuites.add(micros)
+
+            mx.run_java(['-jar', microJar, "-l"], cwd = jmhPath, out = _addBenchmark, addDefaultArgs = False)
+        else:
+            matchedSuites.add(micros)
+
+    mx.logv("matchedSuites: " + str(matchedSuites))
+    plural = 's' if not benchmarks or numBench[0] > 1 else ''
+    number = str(numBench[0]) if benchmarks else "all"
+    mx.log("Running " + number + " benchmark" + plural + '...')
+
+    regex = []
+    if benchmarks:
+        regex.append(r".*(" + "|".join(benchmarks) + ").*")
+
+    for suite in matchedSuites:
+        absoluteMicro = os.path.join(jmhPath, suite)
+        (pfx, exe, vm, forkedVmArgs, _) = _parseVmArgs(vmArgs)
+        if pfx:
+            mx.warn("JMH ignores prefix: \"" + pfx + "\"")
+        mx.run_java(
+           ['-jar', os.path.join(absoluteMicro, "target", "microbenchmarks.jar"),
+            "-f", "1",
+            "-i", "10", "-wi", "10",
+            "--jvm", exe,
+            "--jvmArgs", " ".join(["-" + vm] + forkedVmArgs)] + regex,
+            addDefaultArgs = False,
+            cwd = jmhPath)
+
+
 def specjvm2008(args):
     """run one or more SPECjvm2008 benchmarks"""
 
@@ -1535,6 +1616,7 @@
         'hcfdis': [hcfdis, ''],
         'igv' : [igv, ''],
         'jdkhome': [print_jdkhome, ''],
+        'jmh': [jmh, '[VM options] [filters...]'],
         'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'],
         'scaladacapo': [scaladacapo, '[VM options] benchmarks...|"all" [Scala DaCapo options]'],
         'specjvm2008': [specjvm2008, '[VM options] benchmarks...|"all" [SPECjvm2008 options]'],
--- a/mx/projects	Thu Feb 06 17:41:51 2014 +0100
+++ b/mx/projects	Mon Feb 17 13:48:41 2014 +0100
@@ -37,26 +37,26 @@
 library@JRUBYPARSER@path=lib/jrubyparser-0.5.0.jar
 library@JRUBYPARSER@urls=http://repo1.maven.org/maven2/org/jruby/jrubyparser/0.5.0/jrubyparser-0.5.0.jar
 
-library@JLINE@path=lib/jline-2.10.jar
-library@JLINE@urls=http://repo1.maven.org/maven2/jline/jline/2.10/jline-2.10.jar
+library@JLINE@path=lib/jline-2.11.jar
+library@JLINE@urls=http://repo1.maven.org/maven2/jline/jline/2.11/jline-2.11.jar
 
 library@JRUBYSTDLIB@path=lib/jruby-stdlib-1.7.4.jar
 library@JRUBYSTDLIB@urls=http://repo1.maven.org/maven2/org/jruby/jruby-stdlib/1.7.4/jruby-stdlib-1.7.4.jar
 
-library@JNR_POSIX@path=lib/jnr-posix-3.0.0.jar
-library@JNR_POSIX@urls=http://repo1.maven.org/maven2/com/github/jnr/jnr-posix/3.0.0/jnr-posix-3.0.0.jar
+library@JNR_POSIX@path=lib/jnr-posix-3.0.1.jar
+library@JNR_POSIX@urls=http://repo1.maven.org/maven2/com/github/jnr/jnr-posix/3.0.1/jnr-posix-3.0.1.jar
 
-library@JNR_CONSTANTS@path=lib/jnr-constants-0.8.4.jar
-library@JNR_CONSTANTS@urls=http://repo1.maven.org/maven2/com/github/jnr/jnr-constants/0.8.4/jnr-constants-0.8.4.jar
+library@JNR_CONSTANTS@path=lib/jnr-constants-0.8.5.jar
+library@JNR_CONSTANTS@urls=http://repo1.maven.org/maven2/com/github/jnr/jnr-constants/0.8.5/jnr-constants-0.8.5.jar
 
-library@JNR_FFI@path=lib/jnr-ffi-1.0.4.jar
-library@JNR_FFI@urls=http://repo1.maven.org/maven2/com/github/jnr/jnr-ffi/1.0.4/jnr-ffi-1.0.4.jar
+library@JNR_FFI@path=lib/jnr-ffi-1.0.10.jar
+library@JNR_FFI@urls=http://repo1.maven.org/maven2/com/github/jnr/jnr-ffi/1.0.10/jnr-ffi-1.0.10.jar
 
-library@JFFI@path=lib/jffi-1.2.1.jar
-library@JFFI@urls=http://repo1.maven.org/maven2/com/github/jnr/jffi/1.2.1/jffi-1.2.1.jar
+library@JFFI@path=lib/jffi-1.2.7.jar
+library@JFFI@urls=http://repo1.maven.org/maven2/com/github/jnr/jffi/1.2.7/jffi-1.2.7.jar
 
-library@JFFI_NATIVE@path=lib/jffi-1.2.1-native.jar
-library@JFFI_NATIVE@urls=http://search.maven.org/remotecontent?filepath=com/github/jnr/jffi/1.2.1/jffi-1.2.1-native.jar
+library@JFFI_NATIVE@path=lib/jffi-1.2.7-native.jar
+library@JFFI_NATIVE@urls=http://search.maven.org/remotecontent?filepath=com/github/jnr/jffi/1.2.7/jffi-1.2.7-native.jar
 
 library@JNR_X86ASM@path=lib/jnr-x86asm-1.0.2.jar
 library@JNR_X86ASM@urls=http://repo1.maven.org/maven2/com/github/jnr/jnr-x86asm/1.0.2/jnr-x86asm-1.0.2.jar
@@ -184,7 +184,7 @@
 # graal.hotspot.amd64
 project@com.oracle.graal.hotspot.amd64@subDir=graal
 project@com.oracle.graal.hotspot.amd64@sourceDirs=src
-project@com.oracle.graal.hotspot.amd64@dependencies=com.oracle.graal.nfi.hotspot.amd64,com.oracle.graal.replacements.amd64
+project@com.oracle.graal.hotspot.amd64@dependencies=com.oracle.graal.compiler.amd64,com.oracle.graal.hotspot,com.oracle.graal.replacements.amd64
 project@com.oracle.graal.hotspot.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.amd64@annotationProcessors=com.oracle.graal.service.processor
 project@com.oracle.graal.hotspot.amd64@javaCompliance=1.7
@@ -651,22 +651,6 @@
 project@com.oracle.graal.asm.sparc@javaCompliance=1.7
 project@com.oracle.graal.asm.sparc@workingSets=Graal,Assembler,SPARC
 
-# graal.nfi.hotspot.amd64
-project@com.oracle.graal.nfi.hotspot.amd64@subDir=graal
-project@com.oracle.graal.nfi.hotspot.amd64@sourceDirs=src
-project@com.oracle.graal.nfi.hotspot.amd64@dependencies=com.oracle.graal.compiler.amd64,com.oracle.graal.hotspot
-project@com.oracle.graal.nfi.hotspot.amd64@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.nfi.hotspot.amd64@javaCompliance=1.7
-project@com.oracle.graal.nfi.hotspot.amd64@workingSets=Graal,AMD64
-
-# graal.nfi.test
-project@com.oracle.graal.nfi.test@subDir=graal
-project@com.oracle.graal.nfi.test@sourceDirs=test
-project@com.oracle.graal.nfi.test@dependencies=JUNIT,com.oracle.graal.runtime
-project@com.oracle.graal.nfi.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.graal.nfi.test@javaCompliance=1.7
-project@com.oracle.graal.nfi.test@workingSets=Graal,Test
-
 # truffle.api
 project@com.oracle.truffle.api@subDir=graal
 project@com.oracle.truffle.api@sourceDirs=src
--- a/mxtool/mx.py	Thu Feb 06 17:41:51 2014 +0100
+++ b/mxtool/mx.py	Mon Feb 17 13:48:41 2014 +0100
@@ -38,6 +38,7 @@
 import socket
 import xml.parsers.expat
 import shutil, re, xml.dom.minidom
+import pipes
 from collections import Callable
 from threading import Thread
 from argparse import ArgumentParser, REMAINDER
@@ -989,7 +990,7 @@
         self.add_argument('-d', action='store_const', const=8000, dest='java_dbg_port', help='alias for "-dbg 8000"')
         self.add_argument('--cp-pfx', dest='cp_prefix', help='class path prefix', metavar='<arg>')
         self.add_argument('--cp-sfx', dest='cp_suffix', help='class path suffix', metavar='<arg>')
-        self.add_argument('--J', dest='java_args', help='Java VM arguments (e.g. --J @-dsa)', metavar='@<args>', default='-ea -Xss2m -Xmx1g')
+        self.add_argument('--J', dest='java_args', help='Java VM arguments (e.g. --J @-dsa)', metavar='@<args>')
         self.add_argument('--Jp', action='append', dest='java_args_pfx', help='prefix Java VM arguments (e.g. --Jp @-dsa)', metavar='@<args>', default=[])
         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('~'))
@@ -1052,8 +1053,8 @@
     assert _java is not None
     return _java
 
-def run_java(args, nonZeroIsFatal=True, out=None, err=None, cwd=None):
-    return run(java().format_cmd(args), nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd)
+def run_java(args, nonZeroIsFatal=True, out=None, err=None, cwd=None, addDefaultArgs=True):
+    return run(java().format_cmd(args, addDefaultArgs), nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd)
 
 def _kill_process_group(pid):
     pgid = os.getpgid(pid)
@@ -1131,7 +1132,7 @@
             log('Environment variables:')
             for key in sorted(env.keys()):
                 log('    ' + key + '=' + env[key])
-        log(' '.join(args))
+        log(' '.join(map(pipes.quote, args)))
 
     if timeout is None and _opts.ptimeout != 0:
         timeout = _opts.ptimeout
@@ -1309,7 +1310,7 @@
         def delAtAndSplit(s):
             return shlex.split(s.lstrip('@'))
 
-        self.java_args = delAtAndSplit(_opts.java_args)
+        self.java_args = delAtAndSplit(_opts.java_args) if _opts.java_args else []
         self.java_args_pfx = sum(map(delAtAndSplit, _opts.java_args_pfx), [])
         self.java_args_sfx = sum(map(delAtAndSplit, _opts.java_args_sfx), [])
 
@@ -1332,8 +1333,14 @@
         if self.debug_port is not None:
             self.java_args += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(self.debug_port)]
 
-    def format_cmd(self, args):
-        return [self.java] + self.java_args_pfx + self.java_args + self.java_args_sfx + args
+    def format_cmd(self, args, addDefaultArgs):
+        if addDefaultArgs:
+            return [self.java] + self.processArgs(args)
+        else:
+            return [self.java] + args
+
+    def processArgs(self, args):
+        return self.java_args_pfx + self.java_args + self.java_args_sfx + args
 
     def bootclasspath(self):
         if self._bootclasspath is None:
@@ -1557,6 +1564,7 @@
     parser.add_argument('--only', action='store', help='comma separated projects to build, without checking their dependencies (omit to build all projects)')
     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('--force-javac', action='store_true', dest='javac', help='use javac despite ecj.jar is found or not')
     parser.add_argument('--jdt', help='path to ecj.jar, 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')
 
@@ -1566,12 +1574,16 @@
     args = parser.parse_args(args)
 
     jdtJar = None
-    if args.jdt is not None:
-        if args.jdt.endswith('.jar'):
-            jdtJar = args.jdt
-            if not exists(jdtJar) and os.path.abspath(jdtJar) == os.path.abspath(defaultEcjPath) and get_env('JDT', None) is None:
-                # Silently ignore JDT if default location is used but not ecj.jar exists there
+    if not args.javac and args.jdt is not None:
+        if not args.jdt.endswith('.jar'):
+            abort('Path for Eclipse batch compiler does not look like a jar file: ' + args.jdt)
+        jdtJar = args.jdt
+        if not exists(jdtJar):
+            if os.path.abspath(jdtJar) == os.path.abspath(defaultEcjPath) and get_env('JDT', None) is None:
+                # Silently ignore JDT if default location is used but does not exist
                 jdtJar = None
+            else:
+                abort('Eclipse batch compiler jar does not exist: ' + args.jdt)
 
     built = set()
 
--- a/src/gpu/hsail/vm/hsailKernelArguments.cpp	Thu Feb 06 17:41:51 2014 +0100
+++ b/src/gpu/hsail/vm/hsailKernelArguments.cpp	Mon Feb 17 13:48:41 2014 +0100
@@ -70,7 +70,7 @@
   jvalue jValue;
   java_lang_boxing_object::get_value(arg, &jValue);
   if (TraceGPUInteraction) {
-    tty->print_cr("[HSAIL] HSAILKernelArguments::double value = %e", jValue.d);
+    tty->print_cr("[HSAIL] HSAILKernelArguments::do_double, _index=%d, value = %e", _index - 1, jValue.d);
   }  
   bool pushed = Hsail::_okra_push_double(_kernel, jValue.d);
   assert(pushed == true, "arg push failed");
@@ -84,7 +84,7 @@
   jvalue jValue;
   java_lang_boxing_object::get_value(arg, &jValue);
   if (TraceGPUInteraction) {
-    tty->print_cr("[HSAIL] HSAILKernelArguments::float value = %f", jValue.f);
+    tty->print_cr("[HSAIL] HSAILKernelArguments::do_float, _index=%d, value = %f", _index - 1, jValue.f);
   }    
   bool pushed = Hsail::_okra_push_float(_kernel, jValue.f);
   assert(pushed == true, "float push failed");
@@ -93,7 +93,7 @@
 void HSAILKernelArguments::do_int() {
   // The last int is the iteration variable in an IntStream, but we don't pass it
   // since we use the HSAIL workitemid in place of that int value
-  if (_parameter_index == _parameter_count - 1) {
+  if (isLastParameter()) {
     if (TraceGPUInteraction) {
       tty->print_cr("[HSAIL] HSAILKernelArguments::not pushing trailing int");
     }
@@ -106,6 +106,9 @@
   
   jvalue jValue;
   java_lang_boxing_object::get_value(arg, &jValue);
+  if (TraceGPUInteraction) {
+    tty->print_cr("[HSAIL] HSAILKernelArguments::do_int, _index=%d, value = %d", _index - 1, jValue.i);
+  }    
   
   bool pushed = Hsail::_okra_push_int(_kernel, jValue.i);
   assert(pushed == true, "arg push failed");
@@ -118,6 +121,9 @@
   
   jvalue jValue;
   java_lang_boxing_object::get_value(arg, &jValue);
+  if (TraceGPUInteraction) {
+    tty->print_cr("[HSAIL] HSAILKernelArguments::do_long, _index=%d, value = %d", _index - 1, jValue.j);
+  }    
   
   bool pushed = Hsail::_okra_push_long(_kernel, jValue.j);
   assert(pushed == true, "arg push failed");  
@@ -127,7 +133,7 @@
   oop arg = _args->obj_at(_index++);
   assert(arg->is_array(), "arg type mismatch");
   if (TraceGPUInteraction) {
-    tty->print_cr("[HSAIL] HSAILKernelArguments::do_array 0x%08x, is a %s", (address) arg, arg->klass()->external_name());
+    tty->print_cr("[HSAIL] HSAILKernelArguments::do_array, _index=%d, 0x%08x, is a %s", _index - 1, (address) arg, arg->klass()->external_name());
   }
     
   bool pushed = Hsail::_okra_push_object(_kernel, arg);
@@ -135,14 +141,14 @@
 }
 
 void HSAILKernelArguments::do_object() {
-  if (TraceGPUInteraction) {
-    tty->print_cr("[HSAIL] HSAILKernelArguments::do_object, _parameter_index=%d", _parameter_index);
-  }
+  
+  bool isLastParam = isLastParameter();  // determine this before incrementing _index
+
   oop arg = _args->obj_at(_index++);
 
   // check if this is last arg in signature
   // an object as last parameter requires an object stream source array to be passed
-  if (_parameter_index == _parameter_count - 1) {
+  if (isLastParam) {
     if (TraceGPUInteraction) {
       tty->print_cr("[HSAIL] HSAILKernelArguments::trailing object ref should be object source array ref");
     }
@@ -150,7 +156,7 @@
   }
 
   if (TraceGPUInteraction) {
-    tty->print_cr("[HSAIL] HSAILKernelArguments::do_object, 0x%08x is a %s", (address) arg, arg->klass()->external_name());
+    tty->print_cr("[HSAIL] HSAILKernelArguments::do_object, _index=%d, 0x%08x is a %s", _index - 1, (address) arg, arg->klass()->external_name());
   }
     
   bool pushed = Hsail::_okra_push_object(_kernel, arg);
--- a/src/gpu/hsail/vm/hsailKernelArguments.hpp	Thu Feb 06 17:41:51 2014 +0100
+++ b/src/gpu/hsail/vm/hsailKernelArguments.hpp	Mon Feb 17 13:48:41 2014 +0100
@@ -63,7 +63,8 @@
     _parameter_count = ArgumentCount(signature).size();
 
     if (TraceGPUInteraction) {
-      tty->print_cr("[HSAIL] sig:%s  args length=%d", signature->as_C_string(), _length);
+      char buf[O_BUFLEN];
+      tty->print_cr("[HSAIL] sig:%s  args length=%d, _parameter_count=%d", signature->as_C_string(buf, O_BUFLEN), _length, _parameter_count);
     }    
     if (!_is_static) {      
       // First object in args should be 'this'
@@ -103,6 +104,11 @@
     /* TODO : To be implemented */
     guarantee(false, "do_short:NYI");
   }
+
+  bool isLastParameter() {
+      return  (_index == (_is_static ?  _parameter_count - 1 : _parameter_count));
+  }
+
 };
 
 #endif  // KERNEL_ARGUMENTS_HPP
--- a/src/gpu/ptx/vm/gpu_ptx.cpp	Thu Feb 06 17:41:51 2014 +0100
+++ b/src/gpu/ptx/vm/gpu_ptx.cpp	Mon Feb 17 13:48:41 2014 +0100
@@ -48,7 +48,7 @@
 // Entry to GPU native method implementation that transitions current thread to '_thread_in_vm'.
 #define GPU_VMENTRY(result_type, name, signature) \
   JNIEXPORT result_type JNICALL name signature { \
-  if (TraceGPUInteraction) tty->print_cr("[CUDA] Ptx::" #name); \
+  if (TraceGPUInteraction) tty->print_cr("[CUDA] " #name); \
   GRAAL_VM_ENTRY_MARK; \
 
 // Entry to GPU native method implementation that calls a JNI function
@@ -69,9 +69,10 @@
   {CC"generateKernel",          CC"([B" STRING ")J",   FN_PTR(Ptx::generate_kernel)},
   {CC"getLaunchKernelAddress",  CC"()J",               FN_PTR(Ptx::get_execute_kernel_from_vm_address)},
   {CC"getAvailableProcessors0", CC"()I",               FN_PTR(Ptx::get_total_cores)},
+  {CC"destroyContext",          CC"()V",               FN_PTR(Ptx::destroy_ptx_context)},
 };
 
-void * Ptx::_device_context;
+void * Ptx::_device_context = 0;
 int    Ptx::_cu_device = 0;
 
 Ptx::cuda_cu_init_func_t Ptx::_cuda_cu_init;
@@ -218,8 +219,8 @@
   version = (float) major + ((float) minor)/10;
 
   if (version < GRAAL_SUPPORTED_COMPUTE_CAPABILITY_VERSION) {
-    tty->print_cr("[CUDA] Only cuda compute capability 3.0 and later supported. Device %d supports %.1f",
-                  _cu_device, version);
+    tty->print_cr("[CUDA] Only cuda compute capability %.1f and later supported. Device %d supports %.1f",
+                  (float) GRAAL_SUPPORTED_COMPUTE_CAPABILITY_VERSION, _cu_device, version);
     return false;
   }
 
@@ -253,6 +254,18 @@
     tty->print_cr("[CUDA] Using %s", device_name);
   }
 
+  // Create CUDA context to compile and execute the kernel
+
+  status = _cuda_cu_ctx_create(&_device_context, GRAAL_CU_CTX_MAP_HOST, _cu_device);
+
+  if (status != GRAAL_CUDA_SUCCESS) {
+    tty->print_cr("[CUDA] Failed to create CUDA context for device(%d): %d", _cu_device, status);
+    return false;
+  }
+  if (TraceGPUInteraction) {
+    tty->print_cr("[CUDA] Success: Created context for device: %d", _cu_device);
+  }
+
   gpu::initialized_gpu(device_name);
 
   return true;
@@ -381,23 +394,20 @@
   jit_options[2] = GRAAL_CU_JIT_MAX_REGISTERS;
   jit_option_values[2] = (void *)(size_t)jit_register_count;
 
-  // Create CUDA context to compile and execute the kernel
-  int status = _cuda_cu_ctx_create(&_device_context, GRAAL_CU_CTX_MAP_HOST, _cu_device);
+  // Set CUDA context to compile and execute the kernel
 
-  if (status != GRAAL_CUDA_SUCCESS) {
-    tty->print_cr("[CUDA] Failed to create CUDA context for device(%d): %d", _cu_device, status);
-    return 0L;
-  }
-  if (TraceGPUInteraction) {
-    tty->print_cr("[CUDA] Success: Created context for device: %d", _cu_device);
+  if (_device_context == NULL) {
+    tty->print_cr("[CUDA] Encountered uninitialized CUDA context for device(%d)", _cu_device);
+      return 0L;
   }
 
-  status = _cuda_cu_ctx_set_current(_device_context);
+  int status = _cuda_cu_ctx_set_current(_device_context);
 
   if (status != GRAAL_CUDA_SUCCESS) {
     tty->print_cr("[CUDA] Failed to set current context for device: %d", _cu_device);
     return 0L;
   }
+
   if (TraceGPUInteraction) {
     tty->print_cr("[CUDA] Success: Set current context for device: %d", _cu_device);
     tty->print_cr("[CUDA] PTX Kernel\n%s", code);
@@ -573,17 +583,9 @@
     }
   }
 
-  void destroy_context() {
-    if (Ptx::_device_context != NULL) {
-      check(Ptx::_cuda_cu_ctx_destroy(Ptx::_device_context), "Destroy context");
-      Ptx::_device_context = NULL;
-    }
-  }
-
   ~PtxCall() {
     unpin_objects();
     free_return_value();
-    destroy_context();
     if (_gc_locked) {
       GC_locker::unlock_critical(_thread);
       if (TraceGPUInteraction) {
@@ -669,6 +671,23 @@
   }
 }
 
+GPU_VMENTRY(void, Ptx::destroy_ptx_context, (void))
+    if (_device_context != NULL) {
+      int status = _cuda_cu_ctx_destroy(_device_context);
+      if (status != GRAAL_CUDA_SUCCESS) {
+        if (TraceGPUInteraction) {
+          tty->print_cr("[CUDA] Error(%d) : Failed to destroy context", status);
+        }
+      _device_context = NULL;
+      } else {
+        if (TraceGPUInteraction) {
+          tty->print_cr("[CUDA] Destroyed context", status);
+        }
+      }
+    }
+
+GPU_END
+
 GPU_VMENTRY(jlong, Ptx::get_execute_kernel_from_vm_address, (JNIEnv *env, jclass))
   return (jlong) Ptx::execute_kernel_from_vm;
 GPU_END
@@ -720,7 +739,7 @@
 JRT_END
 
 #if defined(LINUX)
-static const char cuda_library_name[] = "libcuda.so";
+static const char cuda_library_name[] = "/usr/lib/libcuda.so";
 #elif defined(__APPLE__)
 static char const cuda_library_name[] = "/usr/local/cuda/lib/libcuda.dylib";
 #else
--- a/src/gpu/ptx/vm/gpu_ptx.hpp	Thu Feb 06 17:41:51 2014 +0100
+++ b/src/gpu/ptx/vm/gpu_ptx.hpp	Mon Feb 17 13:48:41 2014 +0100
@@ -112,6 +112,8 @@
   // static native int getAvailableProcessors0();
   JNIEXPORT static jint get_total_cores(JNIEnv *env, jobject);
 
+  JNIEXPORT static void destroy_ptx_context();
+
   // Links the CUDA driver library functions
   static bool link();
 
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Feb 06 17:41:51 2014 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Mon Feb 17 13:48:41 2014 +0100
@@ -197,9 +197,14 @@
   HotSpotResolvedJavaMethod::set_ignoredBySecurityStackWalk(hotspot_method, method->is_ignored_by_security_stack_walk());
 C2V_END
 
-C2V_VMENTRY(jboolean, isMethodCompilable,(JNIEnv *, jobject, jlong metaspace_method))
+C2V_VMENTRY(jboolean, canInlineMethod,(JNIEnv *, jobject, jlong metaspace_method))
   methodHandle method = asMethod(metaspace_method);
-  return !method->is_not_compilable() && !CompilerOracle::should_not_inline(method);
+  return !method->is_not_compilable() && !CompilerOracle::should_not_inline(method) && !method->dont_inline();
+C2V_END
+
+C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv *, jobject, jlong metaspace_method))
+  methodHandle method = asMethod(metaspace_method);
+  return CompilerOracle::should_inline(method) || method->force_inline();
 C2V_END
 
 C2V_ENTRY(jint, getCompiledCodeSize, (JNIEnv *env, jobject, jlong metaspace_method))
@@ -558,8 +563,8 @@
 
   //------------------------------------------------------------------------------------------------
 
-  set_long("libraryLoadAddress", (jlong) os::dll_load);
-  set_long("functionLookupAddress", (jlong) os::dll_lookup);
+  set_long("dllLoad", (jlong) os::dll_load);
+  set_long("dllLookup", (jlong) os::dll_lookup);
   #if defined(TARGET_OS_FAMILY_bsd) || defined(TARGET_OS_FAMILY_linux)
   set_long("rtldDefault", (jlong) RTLD_DEFAULT);
   #endif
@@ -883,7 +888,8 @@
   {CC"getStackTraceElement",          CC"("METASPACE_METHOD"I)"STACK_TRACE_ELEMENT,                     FN_PTR(getStackTraceElement)},
   {CC"initializeMethod",              CC"("METASPACE_METHOD HS_RESOLVED_METHOD")V",                     FN_PTR(initializeMethod)},
   {CC"doNotInlineOrCompile",          CC"("METASPACE_METHOD")V",                                        FN_PTR(doNotInlineOrCompile)},
-  {CC"isMethodCompilable",            CC"("METASPACE_METHOD")Z",                                        FN_PTR(isMethodCompilable)},
+  {CC"canInlineMethod",               CC"("METASPACE_METHOD")Z",                                        FN_PTR(canInlineMethod)},
+  {CC"shouldInlineMethod",            CC"("METASPACE_METHOD")Z",                                        FN_PTR(shouldInlineMethod)},
   {CC"getCompiledCodeSize",           CC"("METASPACE_METHOD")I",                                        FN_PTR(getCompiledCodeSize)},
   {CC"lookupType",                    CC"("STRING CLASS"Z)"METASPACE_KLASS,                             FN_PTR(lookupType)},
   {CC"lookupConstantInPool",          CC"("METASPACE_CONSTANT_POOL"I)"OBJECT,                           FN_PTR(lookupConstantInPool)},
--- a/src/share/vm/runtime/compilationPolicy.cpp	Thu Feb 06 17:41:51 2014 +0100
+++ b/src/share/vm/runtime/compilationPolicy.cpp	Mon Feb 17 13:48:41 2014 +0100
@@ -172,16 +172,20 @@
       {
         ResourceMark rm;
         if (klass_name != NULL) {
-          if (klass_name != NULL && method_name != NULL) {
-            const char* lambdaPrefix = "lambda$";
-            char* methodPrefix = strstr(method_name->as_C_string(), lambdaPrefix);
-            if (methodPrefix != 0) {
-              if ((strncmp(lambdaPrefix, methodPrefix, strlen(lambdaPrefix)) == 0)) {
-                if (TraceGPUInteraction) {
-                  char buf[O_BUFLEN];
-                  tty->print_cr("Selected lambda method %s for GPU offload", m->name_and_sig_as_C_string(buf, O_BUFLEN));
+          const char* javaClass = "java/";
+          // Exclude java library classes - for now
+          if (strncmp(klass_name->as_C_string(), javaClass, strlen(javaClass))) {
+            if (method_name != NULL) {
+              const char* lambdaPrefix = "lambda$";
+              char* methodPrefix = strstr(method_name->as_C_string(), lambdaPrefix);
+              if (methodPrefix != 0) {
+                if ((strncmp(lambdaPrefix, methodPrefix, strlen(lambdaPrefix)) == 0)) {
+                  if (TraceGPUInteraction) {
+                    char buf[O_BUFLEN];
+                    tty->print_cr("Selected lambda method %s for GPU offload", m->name_and_sig_as_C_string(buf, O_BUFLEN));
+                  }
+                  return true;
                 }
-                return true;
               }
             }
           }
--- a/src/share/vm/runtime/vmStructs.cpp	Thu Feb 06 17:41:51 2014 +0100
+++ b/src/share/vm/runtime/vmStructs.cpp	Mon Feb 17 13:48:41 2014 +0100
@@ -813,6 +813,34 @@
      static_field(StubRoutines,                _cipherBlockChaining_decryptAESCrypt,          address)                               \
      static_field(StubRoutines,                _updateBytesCRC32,                             address)                               \
      static_field(StubRoutines,                _crc_table_adr,                                address)                               \
+     static_field(StubRoutines,                _jbyte_arraycopy,                              address)                               \
+     static_field(StubRoutines,                _jshort_arraycopy,                             address)                               \
+     static_field(StubRoutines,                _jint_arraycopy,                               address)                               \
+     static_field(StubRoutines,                _jlong_arraycopy,                              address)                               \
+     static_field(StubRoutines,                _oop_arraycopy,                                address)                               \
+     static_field(StubRoutines,                _oop_arraycopy_uninit,                         address)                               \
+     static_field(StubRoutines,                _jbyte_disjoint_arraycopy,                     address)                               \
+     static_field(StubRoutines,                _jshort_disjoint_arraycopy,                    address)                               \
+     static_field(StubRoutines,                _jint_disjoint_arraycopy,                      address)                               \
+     static_field(StubRoutines,                _jlong_disjoint_arraycopy,                     address)                               \
+     static_field(StubRoutines,                _oop_disjoint_arraycopy,                       address)                               \
+     static_field(StubRoutines,                _oop_disjoint_arraycopy_uninit,                address)                               \
+     static_field(StubRoutines,                _arrayof_jbyte_arraycopy,                      address)                               \
+     static_field(StubRoutines,                _arrayof_jshort_arraycopy,                     address)                               \
+     static_field(StubRoutines,                _arrayof_jint_arraycopy,                       address)                               \
+     static_field(StubRoutines,                _arrayof_jlong_arraycopy,                      address)                               \
+     static_field(StubRoutines,                _arrayof_oop_arraycopy,                        address)                               \
+     static_field(StubRoutines,                _arrayof_oop_arraycopy_uninit,                 address)                               \
+     static_field(StubRoutines,                _arrayof_jbyte_disjoint_arraycopy,             address)                               \
+     static_field(StubRoutines,                _arrayof_jshort_disjoint_arraycopy,            address)                               \
+     static_field(StubRoutines,                _arrayof_jint_disjoint_arraycopy,              address)                               \
+     static_field(StubRoutines,                _arrayof_jlong_disjoint_arraycopy,             address)                               \
+     static_field(StubRoutines,                _arrayof_oop_disjoint_arraycopy,               address)                               \
+     static_field(StubRoutines,                _arrayof_oop_disjoint_arraycopy_uninit,        address)                               \
+     static_field(StubRoutines,                _checkcast_arraycopy,                          address)                               \
+     static_field(StubRoutines,                _checkcast_arraycopy_uninit,                   address)                               \
+     static_field(StubRoutines,                _unsafe_arraycopy,                             address)                               \
+     static_field(StubRoutines,                _generic_arraycopy,                            address)                               \
                                                                                                                                      \
   /*****************/                                                                                                                \
   /* SharedRuntime */                                                                                                                \